diff --git a/data-model/.gitattributes b/data-model/.gitattributes new file mode 100644 index 0000000000..8303247a39 --- /dev/null +++ b/data-model/.gitattributes @@ -0,0 +1,8 @@ +.* eol=crlf +*.html eol=crlf +*.java eol=crlf +*.txt eol=crlf +*.css eol=crlf +*.xml eol=crlf +*.js eol=crlf +*.properties eol=crlf \ No newline at end of file diff --git a/data-model/.gitbugtraq b/data-model/.gitbugtraq new file mode 100644 index 0000000000..bacffb702d --- /dev/null +++ b/data-model/.gitbugtraq @@ -0,0 +1,4 @@ +# For SmartGit +[bugtraq "jira"] + url = https://issues.alfresco.com/jira/browse/%BUGID% + logRegex = ([A-Z]+-\\d+) diff --git a/data-model/.gitignore b/data-model/.gitignore new file mode 100644 index 0000000000..4affcb1e79 --- /dev/null +++ b/data-model/.gitignore @@ -0,0 +1,37 @@ +*.class + +# Eclipse +.classpath +.settings +.project + +# Intellij +.idea/ +*.iml +*.iws + +# Vscode +.vscode/ + +# Mac +.DS_Store + +# Maven +target +*.log +*.log.* + +# Mobile Tools for Java (J2ME) + +.mtj +.tmp/ + +# Package Files # + +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml + +hs_err_pid* diff --git a/data-model/.travis.settings.xml b/data-model/.travis.settings.xml new file mode 100644 index 0000000000..dffe7fbfe1 --- /dev/null +++ b/data-model/.travis.settings.xml @@ -0,0 +1,10 @@ + + + + + alfresco-public + ${env.MAVEN_USERNAME} + ${env.MAVEN_PASSWORD} + + + diff --git a/data-model/.travis.yml b/data-model/.travis.yml new file mode 100644 index 0000000000..bb9bf510b1 --- /dev/null +++ b/data-model/.travis.yml @@ -0,0 +1,46 @@ +dist: trusty +sudo: required +language: java +jdk: + - openjdk11 + +cache: + directories: + - $HOME/.m2 + +branches: + only: + - master + - /support\/.*/ + +install: travis_retry mvn install -DskipTests=true -B -V + +stages: + - test + - release + +jobs: + include: + - stage: test + name: "Build and test" + script: travis_retry mvn test + - name: "WhiteSource scan" + # only on SP branches or master and if it is not a PR + if: fork = false AND (branch = master OR branch =~ /support\/SP\/.*/) AND type != pull_request + script: + # Download the latest version of WhiteSource Unified Agent + - curl -LJO https://github.com/whitesource/unified-agent-distribution/raw/master/standAlone/wss-unified-agent.jar + # Run WhiteSource Unified Agent + - java -jar wss-unified-agent.jar -apiKey ${WHITESOURCE_API_KEY} -c .wss-unified-agent.config + - stage: release + name: "Push to Nexus" + if: fork = false AND (branch = master OR branch =~ /support\/.*/) AND type != pull_request AND commit_message !~ /\[no-release\]/ + before_install: + - "cp .travis.settings.xml $HOME/.m2/settings.xml" + script: + # Use full history for release + - git checkout -B "${TRAVIS_BRANCH}" + # Add email to link commits to user + - git config user.email "${GIT_EMAIL}" + # Skip building of release commits + - mvn --batch-mode -q -DscmCommentPrefix="[maven-release-plugin][skip ci] " -Dusername="${GIT_USERNAME}" -Dpassword="${GIT_PASSWORD}" -DskipTests -Darguments=-DskipTests release:clean release:prepare release:perform \ No newline at end of file diff --git a/data-model/.wss-unified-agent.config b/data-model/.wss-unified-agent.config new file mode 100644 index 0000000000..de58dbbf6b --- /dev/null +++ b/data-model/.wss-unified-agent.config @@ -0,0 +1,228 @@ +#################################################################### +# WhiteSource Unified-Agent configuration file +#################################################################### +########################################## +# GENERAL SCAN MODE: Files and Package Managers +########################################## + +checkPolicies=true +forceCheckAllDependencies=true +forceUpdate=true +forceUpdate.failBuildOnPolicyViolation=true +offline=false +#ignoreSourceFiles=true +#scanComment= +#updateInventory=false +#resolveAllDependencies=false +#failErrorLevel=ALL +#requireKnownSha1=false +#generateScanReport=true +#scanReportTimeoutMinutes=10 +#excludeDependenciesFromNodes=.*commons-io.*,.*maven-model + +#projectPerFolder=true +#projectPerFolderIncludes= +#projectPerFolderExcludes= + +#wss.connectionTimeoutMinutes=60 +# Change the below URL to your WhiteSource server. +# Use the 'WhiteSource Server URL' which can be retrieved +# from your 'Profile' page on the 'Server URLs' panel. +# Then, add the '/agent' path to it. +wss.url=https://saas.whitesourcesoftware.com/agent + +#npm.resolveDependencies=false +#npm.ignoreSourceFiles=false +#npm.includeDevDependencies=true +#npm.runPreStep=true +#npm.ignoreNpmLsErrors=true +#npm.ignoreScripts=true +#npm.yarnProject=true +#npm.accessToken= +#npm.identifyByNameAndVersion=true + +#bower.resolveDependencies=false +#bower.ignoreSourceFiles=true +#bower.runPreStep=true + +#nuget.resolvePackagesConfigFiles=false +#nuget.resolveCsProjFiles=false +#nuget.resolveDependencies=false +#nuget.restoreDependencies=true +#nuget.ignoreSourceFiles=true +#nuget.runPreStep=true +#nuget.resolveNuspecFiles=false + +#python.resolveDependencies=false +#python.ignoreSourceFiles=false +#python.ignorePipInstallErrors=true +#python.installVirtualenv=true +#python.resolveHierarchyTree=false +#python.requirementsFileIncludes=requirements.txt +#python.resolveSetupPyFiles=true +#python.runPipenvPreStep=true +#python.pipenvDevDependencies=true +#python.IgnorePipenvInstallErrors=true + +#maven.ignoredScopes=test provided +maven.resolveDependencies=true +#maven.ignoreSourceFiles=true +#maven.aggregateModules=true +maven.ignorePomModules=false +#maven.runPreStep=true +#maven.ignoreMvnTreeErrors=true +#maven.environmentPath= +#maven.m2RepositoryPath= + +#gradle.ignoredScopes= +#gradle.resolveDependencies=false +#gradle.runAssembleCommand=false +#gradle.runPreStep=true +#gradle.ignoreSourceFiles=true +#gradle.aggregateModules=true +#gradle.preferredEnvironment=wrapper +#gradle.localRepositoryPath= + +#paket.resolveDependencies=false +#paket.ignoredGroups= +#paket.ignoreSourceFiles=false +#paket.runPreStep=true +#paket.exePath= + +#go.resolveDependencies=false +#go.collectDependenciesAtRuntime=true +#go.dependencyManager= +#go.ignoreSourceFiles=true +#go.glide.ignoreTestPackages=false +#go.gogradle.enableTaskAlias=true + +#ruby.resolveDependencies = false +#ruby.ignoreSourceFiles = false +#ruby.installMissingGems = true +#ruby.runBundleInstall = true +#ruby.overwriteGemFile = true + +#sbt.resolveDependencies=false +#sbt.ignoreSourceFiles=true +#sbt.aggregateModules=true +#sbt.runPreStep=true +#sbt.targetFolder= + +#php.resolveDependencies=false +#php.runPreStep=true +#php.includeDevDependencies=true + +#html.resolveDependencies=false + +#cocoapods.resolveDependencies=false +#cocoapods.runPreStep=true +#cocoapods.ignoreSourceFiles=false + +#hex.resolveDependencies=false +#hex.runPreStep=true +#hex.ignoreSourceFiles=false +#hex.aggregateModules=true + +################################## +# Organization tokens: +################################## +apiKey= + +#userKey is required if WhiteSource administrator has enabled "Enforce user level access" option +#userKey= + +projectName=alfresco-data-model +projectVersion=8.25.N +projectToken= + +productName=ACS Community +productVersion= +productToken= +#updateType=APPEND +#requesterEmail=user@provider.com + +######################################################################################### +# Includes/Excludes Glob patterns - PLEASE USE ONLY ONE EXCLUDE LINE AND ONE INCLUDE LINE +######################################################################################### +#includes=**/*.c **/*.cc **/*.cp **/*.cpp **/*.cxx **/*.c++ **/*.h **/*.hpp **/*.hxx + +#includes=**/*.m **/*.mm **/*.js **/*.php +includes=**/*.jar +#includes=**/*.gem **/*.rb +#includes=**/*.dll **/*.cs **/*.nupkg +#includes=**/*.tgz **/*.deb **/*.gzip **/*.rpm **/*.tar.bz2 +#includes=**/*.zip **/*.tar.gz **/*.egg **/*.whl **/*.py + +## Exclude file extensions or specific directories by adding **/*. or **/** +excludes=**/*sources.jar **/*javadoc.jar + +case.sensitive.glob=false +followSymbolicLinks=true + +################################## +# Archive properties +################################## +#archiveExtractionDepth=2 +#archiveIncludes=**/*.war **/*.ear +#archiveExcludes=**/*sources.jar + +################################## +# Proxy settings +################################## +#proxy.host= +#proxy.port= +#proxy.user= +#proxy.pass= + +################################## +# SCM settings +################################## +#scm.type= +#scm.user= +#scm.pass= +#scm.ppk= +#scm.url= +#scm.branch= +#scm.tag= +#scm.npmInstall= +#scm.npmInstallTimeoutMinutes= +#scm.repositoriesFile= + +############################################## +# SCAN MODE: Linux package manager settings +############################################## +#scanPackageManager=true + +################################## +# SCAN MODE: Docker images +################################## +#docker.scanImages=true +#docker.includes=.*.* +#docker.excludes= +#docker.pull.enable=true +#docker.pull.images=.*.* +#docker.pull.maxImages=10 +#docker.pull.tags=.*.* +#docker.pull.digest= +#docker.delete.force=true +#docker.login.sudo=false + +#docker.aws.enable=true +#docker.aws.registryIds= + +################################## +# SCAN MODE: Docker containers +################################## +#docker.scanContainers=true +#docker.containerIncludes=.*.* +#docker.containerExcludes= + +################################ +# Serverless settings +################################ +#serverless.provider= +#serverless.scanFunctions=true +#serverless.includes= +#serverless.excludes= +#serverless.region= +#serverless.maxFunctions=10 diff --git a/data-model/CONTRIBUTING.md b/data-model/CONTRIBUTING.md new file mode 100644 index 0000000000..8d059e27ca --- /dev/null +++ b/data-model/CONTRIBUTING.md @@ -0,0 +1,16 @@ +### Contributing +Thanks for your interest in contributing to this project! + +The following is a set of guidelines for contributing to this library. Most of them will make the life of the reviewer easier and therefore decrease the time required for the patch be included in the next version. + +Because this project forms a part of Alfresco Content Services, the guidelines are hosted in the [Alfresco Social Community](http://community.alfresco.com/community/ecm) where they can be referenced from multiple projects. + +Read an [overview on how this project is goverened](https://community.alfresco.com/docs/DOC-6385-project-overview-repository). + +You can report an issue in the ALF project of the [Alfresco issue tracker](http://issues.alfresco.com). + +Read [instructions for a good issue report](https://community.alfresco.com/docs/DOC-6263-reporting-an-issue). + +Read [instructions for making a contribution](https://community.alfresco.com/docs/DOC-6269-submitting-contributions). + +Please follow [the coding standards](https://community.alfresco.com/docs/DOC-4658-coding-standards). diff --git a/data-model/LICENSE.txt b/data-model/LICENSE.txt new file mode 100644 index 0000000000..65c5ca88a6 --- /dev/null +++ b/data-model/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/data-model/README.md b/data-model/README.md new file mode 100644 index 0000000000..3d9f56bc6c --- /dev/null +++ b/data-model/README.md @@ -0,0 +1,47 @@ +### Alfresco Data Model +[![Build Status](https://travis-ci.com/Alfresco/alfresco-data-model.svg?branch=master)](https://travis-ci.com/Alfresco/alfresco-data-model) + +Data model is a library packaged as a jar file which is part of [Alfresco Content Services Repository](https://community.alfresco.com/docs/DOC-6385-project-overview-repository). +The library contains the following: +* Dictionary, Repository and Search Services interfaces +* Models for data types and Dictionary implementation +* Parsers + +Please note that the data model uses version 2 of the Jackson libraries. +The upgrade from version 1 was not backward compatible, any projects +that are dependent on data model using Jackson 1.x should use the data-model 6.N branch. + +Version 8.0 of data-model depends on alfresco-core 7.0 which is based on Spring 5. + + +### Building and testing +The project can be built and tested by running Maven command: +~~~ +mvn clean install +~~~ + +### Artifacts +The artifacts can be obtained by: +* downloading from [Alfresco repository](https://artifacts.alfresco.com/nexus/content/groups/public) +* getting as Maven dependency by adding the dependency to your pom file: +~~~ + + org.alfresco + alfresco-data-model + version + +~~~ +and Alfresco repository: +~~~ + + alfresco-maven-repo + https://artifacts.alfresco.com/nexus/content/groups/public + +~~~ +The SNAPSHOT version of the artifact is **never** published. + +### Old version history +The history for older versions can be found in [Alfresco SVN](https://svn.alfresco.com/repos/alfresco-open-mirror/alfresco/HEAD/root/projects/data-model) + +### Contributing guide +Please use [this guide](CONTRIBUTING.md) to make a contribution to the project. diff --git a/data-model/l10n.properties b/data-model/l10n.properties new file mode 100644 index 0000000000..8867ddf32c --- /dev/null +++ b/data-model/l10n.properties @@ -0,0 +1,6 @@ +# Branch specific configuration file for localisation scripts + +MESSAGE_SEARCH_PATH="src/main/resources/alfresco/messages/dictionary-model*.properties" + +EXCLUDED_FILES="src/main/resources/alfresco/messages/dictionary-messages.properties src/main/resources/alfresco/model/dataTypeAnalyzers.properties src/main/resources/alfresco/model/dataTypeAnalyzers_cs.properties src/main/resources/alfresco/model/dataTypeAnalyzers_da.properties src/main/resources/alfresco/model/dataTypeAnalyzers_de.properties src/main/resources/alfresco/model/dataTypeAnalyzers_el.properties src/main/resources/alfresco/model/dataTypeAnalyzers_en.properties src/main/resources/alfresco/model/dataTypeAnalyzers_es.properties src/main/resources/alfresco/model/dataTypeAnalyzers_fi.properties src/main/resources/alfresco/model/dataTypeAnalyzers_fr.properties src/main/resources/alfresco/model/dataTypeAnalyzers_it.properties src/main/resources/alfresco/model/dataTypeAnalyzers_ja.properties src/main/resources/alfresco/model/dataTypeAnalyzers_ko.properties src/main/resources/alfresco/model/dataTypeAnalyzers_nl.properties src/main/resources/alfresco/model/dataTypeAnalyzers_no.properties src/main/resources/alfresco/model/dataTypeAnalyzers_pt.properties src/main/resources/alfresco/model/dataTypeAnalyzers_pt_BR.properties src/main/resources/alfresco/model/dataTypeAnalyzers_ru.properties src/main/resources/alfresco/model/dataTypeAnalyzers_sv.properties src/main/resources/alfresco/model/dataTypeAnalyzers_th.properties src/main/resources/alfresco/model/dataTypeAnalyzers_zh.properties" + diff --git a/data-model/pom.xml b/data-model/pom.xml new file mode 100644 index 0000000000..d7162de1ef --- /dev/null +++ b/data-model/pom.xml @@ -0,0 +1,361 @@ + + 4.0.0 + + + org.alfresco + alfresco-super-pom + 10 + + + alfresco-data-model + Alfresco Data Model + Alfresco Data Model classes + 8.25.11.1-SNAPSHOT + + + scm:git:https://github.com/Alfresco/alfresco-data-model.git + scm:git:https://github.com/Alfresco/alfresco-data-model.git + https://github.com/Alfresco/alfresco-data-model + HEAD + + + + + alfresco-public + https://artifacts.alfresco.com/nexus/content/repositories/releases + + + + + 7.5.7.0 + 3.3.2 + + + source/java/org/alfresco/repo/search/impl/parsers/CMIS*er.java, + source/java/org/alfresco/repo/search/impl/parsers/FTSParser.java, + source/java/org/alfresco/repo/search/impl/parsers/FTSLexer.java + + 11 + + + + + + org.jibx + maven-jibx-plugin + + true + ${project.build.sourceDirectory}/org/alfresco/repo/dictionary + + m2binding.xml + + + + + bind-sources + + bind + + + + + + + + maven-antrun-plugin + + + duplicate-english-messages + generate-resources + + run + + + + + + + + + + + + + + maven-jar-plugin + 3.1.0 + + + + test-jar + + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.jibx + + maven-jibx-plugin + + + [1.2.5,) + + + bind + + + + + true + true + + + + + + + + + maven-release-plugin + + true + @{project.version} + + + + + + + + + + + org.apache.cxf + cxf-rt-frontend-jaxws + ${dependency.cxf.version} + + + org.apache.cxf + cxf-rt-frontend-jaxrs + ${dependency.cxf.version} + + + org.apache.cxf + cxf-rt-rs-client + ${dependency.cxf.version} + + + org.apache.cxf + cxf-rt-transports-http + ${dependency.cxf.version} + + + org.apache.cxf + cxf-rt-ws-policy + ${dependency.cxf.version} + + + + com.github.junrar + junrar + 4.0.0 + + + + org.jsoup + jsoup + 1.11.3 + + + + org.apache.pdfbox + pdfbox + 1.8.16-alfresco-patched + + + org.bouncycastle + bcmail-jdk15on + 1.61 + + + + + + + org.alfresco + alfresco-core + ${dependency.alfresco-core.version} + + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + + jaxen + jaxen + 1.1.6 + + + org.jibx + jibx-run + 1.2.6 + + + + com.fasterxml.jackson.core + jackson-core + 2.9.5 + + + + com.fasterxml.jackson.core + jackson-annotations + 2.9.5 + + + + org.antlr + antlr + 3.5.2 + + + + org.apache.chemistry.opencmis + chemistry-opencmis-client-impl + 1.0.0 + + + junit + junit + + + + + org.apache.chemistry.opencmis + chemistry-opencmis-commons-impl + 1.0.0 + + + com.sun.xml.messaging.saaj + saaj-impl + + + + + org.apache.chemistry.opencmis + chemistry-opencmis-server-bindings + 1.0.0 + + + org.codehaus.woodstox + woodstox-core-asl + 4.2.0 + + + + org.acegisecurity + acegi-security + 0.8.2_patched + + + org.alfresco + alfresco-xmlfactory + 1.3 + + + xerces + xercesImpl + 2.11.0-alfresco-patched-20180402 + + + xpp3 + xpp3 + 1.1.3_8 + + + + org.apache.tika + tika-core + 1.21-20190624-alfresco-patched + + + org.apache.tika + tika-parsers + 1.21-20190624-alfresco-patched + + + com.tdunning + json + + + org.bouncycastle + bcprov-jdk15on + + + asm + asm + + + + + org.gagravarr + vorbis-java-core + 0.8 + + + org.gagravarr + vorbis-java-tika + 0.8 + + + com.googlecode.juniversalchardet + juniversalchardet + 1.0.3 + + + + + junit + junit + 4.12 + test + + + org.antlr + gunit + 3.5.2 + test + + + org.mockito + mockito-all + 1.10.19 + test + + + + diff --git a/data-model/src/main/java/org/alfresco/encoding/TikaCharsetFinder.java b/data-model/src/main/java/org/alfresco/encoding/TikaCharsetFinder.java new file mode 100644 index 0000000000..2c7b98c860 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/encoding/TikaCharsetFinder.java @@ -0,0 +1,95 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.encoding; + +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.tika.parser.txt.CharsetDetector; +import org.apache.tika.parser.txt.CharsetMatch; + +/** + * Uses Apache Tika as a fallback encoding detector + * + * @since 3.4 + * @author Nick Burch + */ +public class TikaCharsetFinder extends AbstractCharactersetFinder +{ + private static Log logger = LogFactory.getLog(TikaCharsetFinder.class); + + private int threshold = 35; + + @Override + protected Charset detectCharsetImpl(byte[] buffer) throws Exception + { + CharsetDetector detector = new CharsetDetector(); + detector.setText(buffer); + CharsetMatch match = detector.detect(); + + if(match != null && match.getConfidence() > threshold) + { + try + { + return Charset.forName(match.getName()); + } + catch(UnsupportedCharsetException e) + { + logger.info("Charset detected as " + match.getName() + " but the JVM does not support this, detection skipped"); + } + } + return null; + } + + /** + * Return the matching threshold before we decide that + * what we detected is a good match. In the range + * 0-100. + */ + public int getThreshold() + { + return threshold; + } + + /** + * At what point do we decide our match is good enough? + * In the range 0-100. If we don't reach the threshold, + * we'll decline, and either another finder will work on + * it or the fallback encoding will be taken. + */ + public void setThreshold(int threshold) + { + if(threshold < 0) + threshold = 0; + if(threshold > 100) + threshold = 100; + + this.threshold = threshold; + } + +} diff --git a/data-model/src/main/java/org/alfresco/model/ContentModel.java b/data-model/src/main/java/org/alfresco/model/ContentModel.java new file mode 100644 index 0000000000..bfac3dc83b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/model/ContentModel.java @@ -0,0 +1,470 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.model; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + + +/** + * Content Model Constants + */ +@AlfrescoPublicApi +public interface ContentModel +{ + // + // System Model Definitions + // + + // type for deleted nodes + static final QName TYPE_DELETED = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "deleted"); + static final QName PROP_ORIGINAL_ID = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "originalId"); + + // base type constants + static final QName TYPE_BASE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "base"); + static final QName ASPECT_REFERENCEABLE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "referenceable"); + static final QName PROP_STORE_PROTOCOL = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "store-protocol"); + static final QName PROP_STORE_IDENTIFIER = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "store-identifier"); + static final QName PROP_NODE_UUID = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "node-uuid"); + static final QName PROP_NODE_DBID = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "node-dbid"); + + // tag for incomplete nodes + static final QName ASPECT_INCOMPLETE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "incomplete"); + + // tag for temporary nodes + static final QName ASPECT_TEMPORARY = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "temporary"); + + // tag for nodes being formed (CIFS) + static final QName ASPECT_NO_CONTENT = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "noContent"); + + // tag for nodes being formed (WebDAV) + static final QName ASPECT_WEBDAV_NO_CONTENT = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "webdavNoContent"); + + static final QName ASPECT_WEBDAV_OBJECT = QName.createQName(NamespaceService.WEBDAV_MODEL_1_0_URI, "object"); + static final QName PROP_DEAD_PROPERTIES = QName.createQName(NamespaceService.WEBDAV_MODEL_1_0_URI, "deadproperties"); + + // tag for localized nodes + static final QName ASPECT_LOCALIZED = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "localized"); + static final QName PROP_LOCALE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "locale"); + + // tag for hidden nodes + static final QName ASPECT_HIDDEN = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "hidden"); + static final QName PROP_VISIBILITY_MASK = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "clientVisibilityMask"); + static final QName PROP_HIDDEN_FLAG = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "hiddenFlag"); + static final QName PROP_CASCADE_HIDDEN = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "cascadeHidden"); + static final QName PROP_CASCADE_INDEX_CONTROL = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "cascadeIndexControl"); + static final QName PROP_CLIENT_CONTROLLED = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "clientControlled"); + + // tag for soft delete (CIFS rename shuffle) + static final QName ASPECT_SOFT_DELETE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "softDelete"); + + // archived nodes aspect constants + static final QName ASPECT_ARCHIVE_ROOT = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archiveRoot"); + static final QName ASSOC_ARCHIVE_USER_LINK = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archiveUserLink"); + static final QName TYPE_ARCHIVE_USER = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archiveUser"); + static final QName ASSOC_ARCHIVED_LINK = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedLink"); + static final QName ASPECT_ARCHIVED = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archived"); + static final QName PROP_ARCHIVED_ORIGINAL_PARENT_ASSOC = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedOriginalParentAssoc"); + static final QName PROP_ARCHIVED_BY = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedBy"); + static final QName PROP_ARCHIVED_DATE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedDate"); + static final QName PROP_ARCHIVED_ORIGINAL_OWNER = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedOriginalOwner"); + static final QName ASPECT_ARCHIVED_ASSOCS = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archived-assocs"); + static final QName PROP_ARCHIVED_PARENT_ASSOCS = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedParentAssocs"); + static final QName PROP_ARCHIVED_CHILD_ASSOCS = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedChildAssocs"); + static final QName PROP_ARCHIVED_SOURCE_ASSOCS = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedSourceAssocs"); + static final QName PROP_ARCHIVED_TARGET_ASSOCS = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedTargetAssocs"); + static final QName ASPECT_ARCHIVE_LOCKABLE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedLockable"); + static final QName PROP_ARCHIVED_LOCK_OWNER = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedLockOwner"); + static final QName PROP_ARCHIVED_LOCK_TYPE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedLockType"); + static final QName PROP_ARCHIVED_LOCK_LIFETIME = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedLockLifetime"); + static final QName PROP_ARCHIVED_EXPIRY_DATE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedExpiryDate"); + static final QName PROP_ARCHIVED_LOCK_ADDITIONAL_INFO = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "archivedLockAdditionalInfo"); + + + // referenceable aspect constants + static final QName TYPE_REFERENCE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "reference"); + static final QName PROP_REFERENCE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "reference"); + + // container type constants + static final QName TYPE_CONTAINER = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "container"); + /** child association type supported by {@link #TYPE_CONTAINER} */ + static final QName ASSOC_CHILDREN =QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "children"); + + // roots + static final QName ASPECT_ROOT = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "aspect_root"); + static final QName TYPE_STOREROOT = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "store_root"); + + // for internal use only: see ALF-13066 / ALF-12358 + static final QName TYPE_LOST_AND_FOUND = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "lost_found"); + static final QName ASSOC_LOST_AND_FOUND = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "lost_found"); + + // descriptor properties + static final QName PROP_SYS_NAME = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "name"); + static final QName PROP_SYS_VERSION_MAJOR = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionMajor"); + static final QName PROP_SYS_VERSION_MINOR = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionMinor"); + static final QName PROP_SYS_VERSION_REVISION = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionRevision"); + static final QName PROP_SYS_VERSION_LABEL = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionLabel"); + static final QName PROP_SYS_VERSION_BUILD = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionBuild"); + static final QName PROP_SYS_VERSION_SCHEMA = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionSchema"); + static final QName PROP_SYS_VERSION_EDITION = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionEdition"); + static final QName PROP_SYS_VERSION_PROPERTIES = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionProperties"); + static final QName PROP_SYS_LICENSE_MODE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "licenseMode"); + + /** + * Aspect for nodes which are by default not deletable. + * @since 3.5.0 + */ + static final QName ASPECT_UNDELETABLE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "undeletable"); + + /** + * Aspect for nodes which are by default not movable. + */ + static final QName ASPECT_UNMOVABLE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "unmovable"); + + /** + * Aspects marking nodes that are pending deletion. + * This aspect is applied to all nodes that are about to be deleted within a transaction. + * The aspect survives only for the duration of calls to delete nodes and their children. + */ + static final QName ASPECT_PENDING_DELETE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "pendingDelete"); + + /** + * Aspect marking nodes for pending set fixed ACL operation and it's contants + */ + static final QName ASPECT_PENDING_FIX_ACL = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "pendingFixAcl"); + static final QName PROP_SHARED_ACL_TO_REPLACE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "sharedAclToReplace"); + static final QName PROP_INHERIT_FROM_ACL = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "inheritFromAcl"); + + // + // Content Model Definitions + // + + // content management type constants + static final QName TYPE_CMOBJECT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "cmobject"); + static final QName PROP_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "name"); + + // copy aspect constants + static final QName ASPECT_COPIEDFROM = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "copiedfrom"); + static final QName ASSOC_ORIGINAL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "original"); + + // working copy aspect contants + static final QName ASPECT_CHECKED_OUT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "checkedOut"); + static final QName ASSOC_WORKING_COPY_LINK = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "workingcopylink"); + static final QName ASPECT_WORKING_COPY = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "workingcopy"); + static final QName PROP_WORKING_COPY_OWNER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "workingCopyOwner"); + static final QName PROP_WORKING_COPY_MODE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "workingCopyMode"); + static final QName PROP_WORKING_COPY_LABEL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "workingCopyLabel"); + + // content type and aspect constants + static final QName TYPE_CONTENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "content"); + static final QName PROP_CONTENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "content"); + + // title aspect + static final QName ASPECT_TITLED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "titled"); + static final QName PROP_TITLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "title"); + static final QName PROP_DESCRIPTION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "description"); + + // auditable aspect + static final QName ASPECT_AUDITABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "auditable"); + static final QName PROP_CREATED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "created"); + static final QName PROP_CREATOR = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "creator"); + static final QName PROP_MODIFIED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modified"); + static final QName PROP_MODIFIER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modifier"); + static final QName PROP_ACCESSED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "accessed"); + + // author aspect + static final QName ASPECT_AUTHOR = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "author"); + static final QName PROP_AUTHOR = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "author"); + + // categories + static final QName TYPE_CATEGORYROOT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "category_root"); + static final QName ASPECT_CLASSIFIABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "classifiable"); + //static final QName ASPECT_CATEGORISATION = QName.createQName(NamespaceService.ALFRESCO_URI, "aspect_categorisation"); + static final QName ASPECT_GEN_CLASSIFIABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "generalclassifiable"); + static final QName TYPE_CATEGORY = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "category"); + static final QName PROP_CATEGORIES = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "categories"); + static final QName ASSOC_CATEGORIES = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "categories"); + static final QName ASSOC_SUBCATEGORIES = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "subcategories"); + + // tags - a subsection of categories + static final QName ASPECT_TAGGABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "taggable"); + static final QName PROP_TAGS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "taggable"); + + // tagscope aspect + static final QName ASPECT_TAGSCOPE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "tagscope"); + static final QName PROP_TAGSCOPE_CACHE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "tagScopeCache"); + static final QName PROP_TAGSCOPE_SUMMARY = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "tagScopeSummary"); + + // ratings + static final QName ASPECT_RATEABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "rateable"); + static final QName ASPECT_LIKES_RATING_SCHEME_ROLLUPS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "likesRatingSchemeRollups"); + static final QName ASPECT_FIVESTAR_RATING_SCHEME_ROLLUPS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "fiveStarRatingSchemeRollups"); + static final QName ASSOC_RATINGS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "ratings"); + static final QName TYPE_RATING = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "rating"); + static final QName PROP_RATING_SCORE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "ratingScore"); + static final QName PROP_RATING_SCHEME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "ratingScheme"); + static final QName PROP_RATED_AT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "ratedAt"); + + // lock aspect + public final static QName ASPECT_LOCKABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lockable"); + public final static QName PROP_LOCK_OWNER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lockOwner"); + public final static QName PROP_LOCK_TYPE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lockType"); + public final static QName PROP_LOCK_LIFETIME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lockLifetime"); + public final static QName PROP_EXPIRY_DATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "expiryDate"); + public final static QName PROP_LOCK_ADDITIONAL_INFO = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lockAdditionalInfo"); + + // version aspect + static final QName ASPECT_VERSIONABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "versionable"); + static final QName PROP_VERSION_LABEL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "versionLabel"); + static final QName PROP_INITIAL_VERSION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "initialVersion"); + static final QName PROP_AUTO_VERSION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "autoVersion"); + static final QName PROP_AUTO_VERSION_PROPS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "autoVersionOnUpdateProps"); + static final QName PROP_VERSION_TYPE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "versionType"); + + // folders + static final QName TYPE_SYSTEM_FOLDER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "systemfolder"); + static final QName TYPE_FOLDER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "folder"); + /** child association type supported by {@link #TYPE_FOLDER} */ + static final QName ASSOC_CONTAINS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "contains"); + + // person + static final QName TYPE_PERSON = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "person"); + static final QName PROP_USERNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "userName"); + static final QName PROP_HOMEFOLDER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "homeFolder"); + static final QName PROP_FIRSTNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "firstName"); + static final QName PROP_LASTNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lastName"); + static final QName PROP_EMAIL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "email"); + static final QName PROP_ORGID = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "organizationId"); + static final QName PROP_HOME_FOLDER_PROVIDER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "homeFolderProvider"); + static final QName PROP_DEFAULT_HOME_FOLDER_PATH = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "defaultHomeFolderPath"); + static final QName PROP_PRESENCEPROVIDER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "presenceProvider"); + static final QName PROP_PRESENCEUSERNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "presenceUsername"); + static final QName PROP_ORGANIZATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "organization"); + static final QName PROP_JOBTITLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "jobtitle"); + static final QName PROP_LOCATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "location"); + static final QName PROP_PERSONDESC = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "persondescription"); + static final QName PROP_TELEPHONE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "telephone"); + static final QName PROP_MOBILE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mobile"); + static final QName PROP_COMPANYADDRESS1 = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companyaddress1"); + static final QName PROP_COMPANYADDRESS2 = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companyaddress2"); + static final QName PROP_COMPANYADDRESS3 = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companyaddress3"); + static final QName PROP_COMPANYPOSTCODE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companypostcode"); + static final QName PROP_COMPANYTELEPHONE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companytelephone"); + static final QName PROP_COMPANYFAX = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companyfax"); + static final QName PROP_COMPANYEMAIL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "companyemail"); + static final QName PROP_SKYPE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "skype"); + static final QName PROP_GOOGLEUSERNAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "googleusername"); + static final QName PROP_INSTANTMSG = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "instantmsg"); + static final QName PROP_USER_STATUS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "userStatus"); + static final QName PROP_USER_STATUS_TIME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "userStatusTime"); + + static final QName PROP_SIZE_CURRENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "sizeCurrent"); // system-maintained + static final QName PROP_SIZE_QUOTA = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "sizeQuota"); + + static final QName PROP_EMAIL_FEED_ID = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "emailFeedId"); // system-maintained + static final QName PROP_EMAIL_FEED_DISABLED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "emailFeedDisabled"); + + static final QName PROP_SUBSCRIPTIONS_PRIVATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "subscriptionsPrivate"); + + static final QName ASPECT_PERSON_DISABLED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "personDisabled"); + + static final QName ASPECT_ANULLABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "annullable"); + + static final QName ASSOC_AVATAR = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "avatar"); + + // Authority + static final QName TYPE_AUTHORITY = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "authority"); + + static final QName TYPE_AUTHORITY_CONTAINER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "authorityContainer"); + static final QName PROP_AUTHORITY_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "authorityName"); + static final QName PROP_AUTHORITY_DISPLAY_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "authorityDisplayName"); + + static final QName ASSOC_MEMBER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "member"); + + // Zone + static final QName TYPE_ZONE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "zone"); + static final QName ASSOC_IN_ZONE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "inZone"); + + // Ownable aspect + static final QName ASPECT_OWNABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "ownable"); + static final QName PROP_OWNER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "owner"); + + // Templatable aspect + static final QName ASPECT_TEMPLATABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "templatable"); + static final QName PROP_TEMPLATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "template"); + + // Webscriptable aspect + static final QName ASPECT_WEBSCRIPTABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "webscriptable"); + static final QName PROP_WEBSCRIPT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "webscript"); + + // Dictionary model + static final QName TYPE_DICTIONARY_MODEL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "dictionaryModel"); + static final QName PROP_MODEL_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modelName"); + static final QName PROP_MODEL_DESCRIPTION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modelDescription"); + static final QName PROP_MODEL_AUTHOR = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modelAuthor"); + static final QName PROP_MODEL_PUBLISHED_DATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modelPublishedDate"); + static final QName PROP_MODEL_VERSION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modelVersion"); + static final QName PROP_MODEL_ACTIVE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "modelActive"); + + // referencing aspect + static final QName ASPECT_REFERENCING = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "referencing"); + static final QName ASSOC_REFERENCES = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "references"); + + // link object + static final QName TYPE_LINK = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "link"); + static final QName PROP_LINK_DESTINATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "destination"); + + // attachable aspect + static final QName ASPECT_ATTACHABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "attachable"); + static final QName ASSOC_ATTACHMENTS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "attachments"); + + // emailed aspect + static final QName ASPECT_EMAILED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "emailed"); + static final QName PROP_SENTDATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "sentdate"); + static final QName PROP_ORIGINATOR = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "originator"); + static final QName PROP_ADDRESSEE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "addressee"); + static final QName PROP_ADDRESSEES = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "addressees"); + static final QName PROP_SUBJECT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "subjectline"); + + // countable aspect + static final QName ASPECT_COUNTABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "countable"); + static final QName PROP_HITS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "hits"); + static final QName PROP_COUNTER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "counter"); + + // References Node Aspect. + static final QName ASPECT_REFERENCES_NODE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "referencesnode"); + static final QName PROP_NODE_REF = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "noderef"); + + // Geographic Aspect. + static final QName ASPECT_GEOGRAPHIC = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "geographic"); + static final QName PROP_LATITUDE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "latitude"); + static final QName PROP_LONGITUDE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "longitude"); + + // Multilingual Type + static final QName TYPE_MULTILINGUAL_CONTAINER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlContainer"); + static final QName ASSOC_MULTILINGUAL_CHILD = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlChild"); + static final QName ASPECT_MULTILINGUAL_DOCUMENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlDocument"); + static final QName ASPECT_MULTILINGUAL_EMPTY_TRANSLATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mlEmptyTranslation"); + + // Thumbnail Type + static final QName TYPE_THUMBNAIL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "thumbnail"); + static final QName PROP_THUMBNAIL_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "thumbnailName"); + static final QName PROP_CONTENT_PROPERTY_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "contentPropertyName"); + static final QName PROP_AUTOMATIC_UPDATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "automaticUpdate"); + + // Thumbnail modification handling + public static final QName ASPECT_THUMBNAIL_MODIFICATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "thumbnailModification"); + public static final QName PROP_LAST_THUMBNAIL_MODIFICATION_DATA = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lastThumbnailModification"); + + // The below content entities can be used to manage 'failed' thumbnails. These are thumbnails that execute and fail with an + // exception that likely means a reattempt will fail. The failedThumbnailSource aspect can be used to mark a node as + // having tried and failed to use a particular thumbnail definition. This can then be checked and reattempts at that thumbnail + // can be prevented or throttled. + static final QName ASPECT_FAILED_THUMBNAIL_SOURCE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "failedThumbnailSource"); + static final QName ASSOC_FAILED_THUMBNAIL= QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "failedThumbnail"); + static final QName TYPE_FAILED_THUMBNAIL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "failedThumbnail"); + static final QName PROP_FAILED_THUMBNAIL_TIME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "failedThumbnailTime"); + static final QName PROP_FAILURE_COUNT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "failureCount"); + + // Thumbnailed Aspect + /** + * This aspect type has been deprecated. + * From Alfresco 3.3 the {@link RenditionModel#ASPECT_RENDITIONED rn:renditioned} + * (which is a child of cm:thumbnailed) should be used instead. + */ + @Deprecated + static final QName ASPECT_THUMBNAILED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "thumbnailed"); + /** + * This association type has been deprecated. + * From Alfresco 3.3 this association no longer exists and has been replaced with + * {@link RenditionModel#ASSOC_RENDITION rn:rendition} association. From Alfresco + * 3.3 onwards a patch is executed at startup which renames + * the cm:thumbnails QName to rn:rendition in the database. + *

+ * This field has been updated to point to that association and references to this + * field should be updated to use the new field. + */ + @Deprecated + static final QName ASSOC_THUMBNAILS = RenditionModel.ASSOC_RENDITION; + + // StoreSelector Aspect + static final QName ASPECT_STORE_SELECTOR = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "storeSelector"); + static final QName PROP_STORE_NAME = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "storeName"); + + // Preference Aspect + static final QName ASPECT_PREFERENCES = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "preferences"); + static final QName PROP_PREFERENCE_VALUES = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "preferenceValues"); + static final QName ASSOC_PREFERENCE_IMAGE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "preferenceImage"); + + // Syndication Aspect + static final QName ASPECT_SYNDICATION = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "syndication"); + static final QName PROP_PUBLISHED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "published"); + static final QName PROP_UPDATED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "updated"); + + // Dublin core aspect + static final QName ASPECT_DUBLINCORE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "dublincore"); + + // + // User Model Definitions + // + + static final String USER_MODEL_URI = "http://www.alfresco.org/model/user/1.0"; + static final String USER_MODEL_PREFIX = "usr"; + + static final QName TYPE_USER = QName.createQName(USER_MODEL_URI, "user"); + static final QName PROP_USER_USERNAME = QName.createQName(USER_MODEL_URI, "username"); + static final QName PROP_PASSWORD = QName.createQName(USER_MODEL_URI, "password"); + static final QName PROP_PASSWORD_SHA256 = QName.createQName(USER_MODEL_URI, "password2"); + static final QName PROP_PASSWORD_HASH = QName.createQName(USER_MODEL_URI, "passwordHash"); + static final QName PROP_ENABLED = QName.createQName(USER_MODEL_URI, "enabled"); + static final QName PROP_ACCOUNT_EXPIRES = QName.createQName(USER_MODEL_URI, "accountExpires"); + static final QName PROP_ACCOUNT_EXPIRY_DATE = QName.createQName(USER_MODEL_URI, "accountExpiryDate"); + static final QName PROP_CREDENTIALS_EXPIRE = QName.createQName(USER_MODEL_URI, "credentialsExpire"); + static final QName PROP_CREDENTIALS_EXPIRY_DATE = QName.createQName(USER_MODEL_URI, "credentialsExpiryDate"); + static final QName PROP_ACCOUNT_LOCKED = QName.createQName(USER_MODEL_URI, "accountLocked"); + static final QName PROP_SALT = QName.createQName(USER_MODEL_URI, "salt"); + static final QName PROP_HASH_INDICATOR = QName.createQName(USER_MODEL_URI, "hashIndicator"); + + // + // Indexing control + // + + static final QName ASPECT_INDEX_CONTROL = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "indexControl"); + static final QName PROP_IS_INDEXED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "isIndexed"); + static final QName PROP_IS_CONTENT_INDEXED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "isContentIndexed"); + + // CMIS aspects + static final QName ASPECT_CMIS_UPDATE_CONTEXT = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "CMISUpdateContext"); + static final QName PROP_GOT_FIRST_CHUNK = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "gotFirstChunk"); + static final QName ASPECT_CMIS_CREATED_CHECKEDOUT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "cmisCreatedCheckedOut"); + + // Cascade Update + static final QName ASPECT_CASCADE_UPDATE = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "cascadeUpdate"); + static final QName PROP_CASCADE_CRC = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "cascadeCRC"); + static final QName PROP_CASCADE_TX = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "cascadeTx"); + +} diff --git a/data-model/src/main/java/org/alfresco/model/RenditionModel.java b/data-model/src/main/java/org/alfresco/model/RenditionModel.java new file mode 100644 index 0000000000..ec57ab0467 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/model/RenditionModel.java @@ -0,0 +1,76 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2018 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.model; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + +/** + * Rendition Model Constants + */ +@AlfrescoPublicApi +public interface RenditionModel +{ + /** + * Aspect added to renditions created by RenditionService2. + * Initially used to avoid duplicate rendition requests via the original RenditionService and the new one. + */ + static final QName ASPECT_RENDITION2 = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "rendition2"); + + /** + * The source node's content hash code. Used to work out if a transform should replace the existing rendition, + * as transforms may be provided out of order. + */ + static final QName PROP_RENDITION_CONTENT_HASH_CODE = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "contentHashCode"); + + /** + * @deprecated This rendition aspect will no longger be needed once the original RenditionService has been + * replaced by RenditionService2 which additionally uses a rendition2 aspect to mark its renditions. + */ + @Deprecated + static final QName ASPECT_RENDITION = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "rendition"); + + /** + * @deprecated obsolete when RenditionService is removed. + */ + @Deprecated + static final QName ASPECT_HIDDEN_RENDITION = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "hiddenRendition"); + + /** + * @deprecated obsolete when RenditionService is removed. + */ + @Deprecated + static final QName ASPECT_VISIBLE_RENDITION = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "visibleRendition"); + + static final QName ASPECT_RENDITIONED = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "renditioned"); + static final QName ASSOC_RENDITION = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "rendition"); + + /** + * @since 4.0.1 + */ + static final QName ASPECT_PREVENT_RENDITIONS = QName.createQName(NamespaceService.RENDITION_MODEL_1_0_URI, "preventRenditions"); +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/CMISAccessControlFormatEnum.java b/data-model/src/main/java/org/alfresco/opencmis/CMISAccessControlFormatEnum.java new file mode 100644 index 0000000000..e4244ae71d --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/CMISAccessControlFormatEnum.java @@ -0,0 +1,71 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis; + +/** + * @author andyh + * + */ +public enum CMISAccessControlFormatEnum implements EnumLabel +{ + /** + * Report only CMIS basic permissions + */ + CMIS_BASIC_PERMISSIONS("onlyBasicPermissions"), + + /** + * May report CMIS basic permission, repository specific permissions or a mixture of both. + */ + REPOSITORY_SPECIFIC_PERMISSIONS("repositorySpecificPermissions"); + + private String label; + + /** + * Construct + * + * @param label String + */ + CMISAccessControlFormatEnum(String label) + { + this.label = label; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.cmis.EnumLabel#label() + */ + public String getLabel() + { + return label; + } + + /** + * Factory for CMISAclPropagationEnum + */ + public static EnumFactory FACTORY = new EnumFactory(CMISAccessControlFormatEnum.class, CMIS_BASIC_PERMISSIONS, true); + +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/CMISUtils.java b/data-model/src/main/java/org/alfresco/opencmis/CMISUtils.java new file mode 100644 index 0000000000..28007b8224 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/CMISUtils.java @@ -0,0 +1,169 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis; + +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; + +import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException; + +public class CMISUtils +{ + @SuppressWarnings("unchecked") + public static T copy(T source) + { + T target = null; + try ( CopyOutputStream cos = new CopyOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(cos) ) + { + out.writeObject(source); + out.flush(); + + try (ObjectInputStream in = new ObjectInputStream(cos.getInputStream())) + { + target = (T) in.readObject(); + } + } catch (Exception e) + { + throw new CmisRuntimeException("Object copy failed!", e); + } + + return target; + } + + private static class CopyOutputStream extends OutputStream + { + protected byte[] buf = null; + protected int size = 0; + + public CopyOutputStream() + { + this(16 * 1024); + } + + public CopyOutputStream(int initSize) + { + this.size = 0; + this.buf = new byte[initSize]; + } + + private void verifyBufferSize(int sz) + { + if (sz > buf.length) + { + byte[] old = buf; + buf = new byte[Math.max(sz, 2 * buf.length)]; + System.arraycopy(old, 0, buf, 0, old.length); + old = null; + } + } + + public final void write(byte b[]) + { + verifyBufferSize(size + b.length); + System.arraycopy(b, 0, buf, size, b.length); + size += b.length; + } + + public final void write(byte b[], int off, int len) + { + verifyBufferSize(size + len); + System.arraycopy(b, off, buf, size, len); + size += len; + } + + public final void write(int b) + { + verifyBufferSize(size + 1); + buf[size++] = (byte) b; + } + + public InputStream getInputStream() + { + return new CopyInputStream(buf, size); + } + } + + private static class CopyInputStream extends InputStream + { + protected byte[] buf = null; + protected int count = 0; + protected int pos = 0; + + public CopyInputStream(byte[] buf, int count) + { + this.buf = buf; + this.count = count; + } + + public final int available() + { + return count - pos; + } + + public final int read() + { + return (pos < count) ? (buf[pos++] & 0xff) : -1; + } + + public final int read(byte[] b, int off, int len) + { + if (pos >= count) + { + return -1; + } + + if ((pos + len) > count) + { + len = (count - pos); + } + + System.arraycopy(buf, pos, b, off, len); + pos += len; + + return len; + } + + public final long skip(long n) + { + if ((pos + n) > count) + { + n = count - pos; + } + + if (n < 0) + { + return 0; + } + + pos += n; + + return n; + } + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/EnumFactory.java b/data-model/src/main/java/org/alfresco/opencmis/EnumFactory.java new file mode 100644 index 0000000000..7fe60b4930 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/EnumFactory.java @@ -0,0 +1,151 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.TreeMap; + + +/** + * Enum Factory for managing mapping between Enum name and Enum label + * + * @author dcaruana + * + */ +public class EnumFactory> +{ + private E defaultEnum; + private Map labelMap = new HashMap(10); + + public EnumFactory(Class enumClass) + { + this(enumClass, null, false); + } + + public EnumFactory(Class enumClass, E defaultEnum) + { + this(enumClass, defaultEnum, false); + } + + /** + * @param caseSensitive case-sensitive lookup for Enum label + */ + public EnumFactory(Class enumClass, E defaultEnum, boolean caseSensitive) + { + this.defaultEnum = defaultEnum; + + // setup label map + labelMap = caseSensitive ? new HashMap(10) : new TreeMap(String.CASE_INSENSITIVE_ORDER); + EnumSet enumSet = EnumSet.allOf(enumClass); + Iterator iter = enumSet.iterator(); + while(iter.hasNext()) + { + E e = iter.next(); + if (e instanceof EnumLabel) + { + labelMap.put(((EnumLabel)e).getLabel(), e); + } + } + } + + /** + * Gets the default enum + * + * @return default enum (or null, if no default specified) + */ + public Enum getDefaultEnum() + { + return defaultEnum; + } + + /** + * Gets the default label + * + * @return label of default enum (or null, if no default specified) + */ + public String getDefaultLabel() + { + return label(defaultEnum); + } + + /** + * Gets the label for the specified enum + * + * @param e enum + * @return label (or null, if no label specified) + */ + public String label(E e) + { + if (e instanceof EnumLabel) + { + return ((EnumLabel)e).getLabel(); + } + return null; + } + + /** + * Is valid label? + * + * @param label String + * @return true => valid, false => does not exist for this enum + */ + public boolean validLabel(String label) + { + return fromLabel(label) == null ? false : true; + } + + /** + * Gets enum from label + * + * @param label String + * @return enum (or null, if no enum has specified label) + */ + public E fromLabel(String label) + { + return labelMap.get(label); + } + + /** + * Gets enum from label + * + * NOTE: If specified label is invalid, the default enum is returned + * + * @param label String + * @return enum (or default enum, if label is invalid) + */ + public E toEnum(String label) + { + E e = (label == null) ? null : fromLabel(label); + if (e == null) + { + e = defaultEnum; + } + return e; + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/EnumLabel.java b/data-model/src/main/java/org/alfresco/opencmis/EnumLabel.java new file mode 100644 index 0000000000..edb1454fde --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/EnumLabel.java @@ -0,0 +1,41 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis; + +/** + * Enum label (mapping from Enum name to CMIS name) + * + * @author davidc + */ +public interface EnumLabel +{ + /** + * Gets the enum label (as defined by CMIS) + * + * @return enum label + */ + public String getLabel(); +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/AbstractTypeDefinitionWrapper.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/AbstractTypeDefinitionWrapper.java new file mode 100644 index 0000000000..69131de33b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/AbstractTypeDefinitionWrapper.java @@ -0,0 +1,813 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.opencmis.mapping.CMISMapping; +import org.alfresco.repo.dictionary.IndexTokenisationMode; +import org.alfresco.repo.dictionary.constraint.ListOfValuesConstraint; +import org.alfresco.repo.dictionary.constraint.NumericRangeConstraint; +import org.alfresco.repo.dictionary.constraint.StringLengthConstraint; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.Constraint; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ISO8601DateFormat; +import org.alfresco.util.ISO9075; +import org.apache.chemistry.opencmis.commons.PropertyIds; +import org.apache.chemistry.opencmis.commons.definitions.Choice; +import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition; +import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition; +import org.apache.chemistry.opencmis.commons.enums.Action; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.chemistry.opencmis.commons.enums.Cardinality; +import org.apache.chemistry.opencmis.commons.enums.CmisVersion; +import org.apache.chemistry.opencmis.commons.enums.PropertyType; +import org.apache.chemistry.opencmis.commons.enums.Updatability; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractPropertyDefinition; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractTypeDefinition; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.ChoiceImpl; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyBooleanDefinitionImpl; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDateTimeDefinitionImpl; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDecimalDefinitionImpl; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyHtmlDefinitionImpl; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIdDefinitionImpl; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerDefinitionImpl; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringDefinitionImpl; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyUriDefinitionImpl; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Base class for type definition wrappers. + * + * @author florian.mueller + */ +public abstract class AbstractTypeDefinitionWrapper implements TypeDefinitionWrapper, Serializable +{ + private static final long serialVersionUID = 1L; + private Log logger = LogFactory.getLog(AbstractTypeDefinitionWrapper.class); + + protected AbstractTypeDefinition typeDef; + protected AbstractTypeDefinition typeDefInclProperties; + + protected TypeDefinitionWrapper parent; +// protected List children; + + private String tenantId; + private ReadWriteLock lock = new ReentrantReadWriteLock(); + + @Override + public String getTenantId() + { + return tenantId; + } + + protected QName alfrescoName = null; + protected QName alfrescoClass = null; + protected Map actionEvaluators; + + protected Map propertiesById = new HashMap(); + protected Map propertiesByQueryName = new HashMap(); + protected Map propertiesByQName = new HashMap(); + + // interface + + public TypeDefinition getTypeDefinition(boolean includePropertyDefinitions) + { + lock.readLock().lock(); + try + { + if (includePropertyDefinitions) + { + return typeDefInclProperties; + } + else + { + return typeDef; + } + } + finally + { + lock.readLock().unlock(); + } + } + + protected void setTypeDefinition(AbstractTypeDefinition typeDef, AbstractTypeDefinition typeDefInclProperties) + { + this.typeDef = typeDef; + this.typeDefInclProperties = typeDefInclProperties; + } + + @Override + public String getTypeId() + { + return typeDef.getId(); + } + + @Override + public BaseTypeId getBaseTypeId() + { + return typeDef.getBaseTypeId(); + } + + @Override + public boolean isBaseType() + { + return typeDef.getId().equals(typeDef.getBaseTypeId().value()); + } + + @Override + public QName getAlfrescoName() + { + return alfrescoName; + } + + @Override + public QName getAlfrescoClass() + { + return alfrescoClass; + } + + @Override + public TypeDefinitionWrapper getParent() + { + return parent; + } + +// @Override +// public List getChildren() +// { +// return children; +// } + + @Override + public Map getActionEvaluators() + { + return actionEvaluators; + } + + @Override + public Collection getProperties() + { + return propertiesById.values(); + } + + @Override + public PropertyDefinitionWrapper getPropertyById(String propertyId) + { + return propertiesById.get(propertyId); + } + + @Override + public PropertyDefinitionWrapper getPropertyByQueryName(String queryName) + { + return propertiesByQueryName.get(queryName); + } + + @Override + public PropertyDefinitionWrapper getPropertyByQName(QName name) + { + return propertiesByQName.get(name); + } + + @Override + public void updateDefinition(DictionaryService dictionaryService) + { + String name = null; + String description = null; + ClassDefinition definition = dictionaryService.getClass(alfrescoName); + + if (definition != null) + { + name = definition.getTitle(dictionaryService); + description = definition.getDescription(dictionaryService); + } + setTypeDefDisplayName(name); + setTypeDefDescription(description); + } + + public void updateProperties(DictionaryService dictionaryService) + { + for (PropertyDefinitionWrapper propertyDefWrap : propertiesById.values()) + { + updateProperty(dictionaryService, propertyDefWrap); + } + } + + public void updateProperty(DictionaryService dictionaryService, PropertyDefinitionWrapper propertyDefWrap) + { + if (propertyDefWrap != null && propertyDefWrap.getPropertyDefinition().getDisplayName() == null) + { + AbstractPropertyDefinition property = (AbstractPropertyDefinition) propertyDefWrap.getPropertyDefinition(); + org.alfresco.service.cmr.dictionary.PropertyDefinition propDef = dictionaryService + .getProperty(QName.createQName(property.getLocalNamespace(), property.getLocalName())); + if (propDef != null) + { + String displayName = propDef.getTitle(dictionaryService); + String description = propDef.getDescription(dictionaryService); + property.setDisplayName(displayName == null ? property.getId() : displayName); + property.setDescription(description == null ? property.getDisplayName() : description); + } + } + } + + public void updateTypeDefInclProperties() + { + for (PropertyDefinition property : typeDefInclProperties.getPropertyDefinitions().values()) + { + if (property.getDisplayName() == null) + { + typeDefInclProperties.addPropertyDefinition(getPropertyById(property.getId()).getPropertyDefinition()); + } + } + } + + public void setTypeDefDisplayName(String name) + { + lock.writeLock().lock(); + try + { + typeDef.setDisplayName(name != null ? name : typeDef.getId()); + typeDefInclProperties.setDisplayName(name != null ? name : typeDef.getId()); + } + finally + { + lock.writeLock().unlock(); + } + } + + public void setTypeDefDescription(String desc) + { + lock.writeLock().lock(); + try + { + typeDef.setDescription(desc != null ? desc : typeDef.getId()); + typeDefInclProperties.setDescription(desc != null ? desc : typeDef.getId()); + } + finally + { + lock.writeLock().unlock(); + } + } + + // create + + public abstract List connectParentAndSubTypes(CMISMapping cmisMapping, CMISDictionaryRegistry registry, + DictionaryService dictionaryService); + + public abstract void resolveInheritance(CMISMapping cmisMapping, CMISDictionaryRegistry registry, + DictionaryService dictionaryService); + + public void assertComplete() + { + if (typeDef == null) + throw new IllegalStateException("typeDef is not set"); + if (typeDefInclProperties == null) + throw new IllegalStateException("typeDefInclProperties is not set"); + if (alfrescoName == null) + throw new IllegalStateException("alfrescoName is not set"); + if (alfrescoClass == null) + throw new IllegalStateException("alfrescoClass is not set"); + if (propertiesById == null) + throw new IllegalStateException("propertiesById is not set"); + if (propertiesByQueryName == null) + throw new IllegalStateException("propertiesByQueryName is not set"); + if (propertiesByQName == null) + throw new IllegalStateException("propertiesByQName is not set"); +// if (propertiesById.size() == 0) +// throw new IllegalStateException("property map empty"); + if (propertiesById.size() != propertiesByQueryName.size()) + throw new IllegalStateException("property map mismatch"); + if (propertiesById.size() != propertiesByQName.size()) + throw new IllegalStateException("property map mismatch"); + } + + /** + * Adds all property definitions owned by that type. + */ + protected void createOwningPropertyDefinitions(CMISMapping cmisMapping, + PropertyAccessorMapping propertyAccessorMapping, PropertyLuceneBuilderMapping luceneBuilderMapping, + DictionaryService dictionaryService, ClassDefinition cmisClassDef) + { + PropertyDefinition propertyDefintion; + + for (org.alfresco.service.cmr.dictionary.PropertyDefinition alfrescoPropDef : cmisClassDef.getProperties() + .values()) + { + if (!isBaseType()) + { + if (!alfrescoPropDef.getContainerClass().equals(cmisClassDef)) + { + continue; + } + } + + // compile property id + String propertyId = cmisMapping.buildPrefixEncodedString(alfrescoPropDef.getName()); + + if(propertyId.equals("cmis:secondaryObjectTypeIds") && cmisMapping.getCmisVersion() == CmisVersion.CMIS_1_0) + { + continue; + } + + // create property definition + propertyDefintion = createPropertyDefinition(cmisMapping, propertyId, alfrescoPropDef.getName(), + dictionaryService, alfrescoPropDef, false); + + // if the datatype is not supported, the property defintion will be + // null + if (propertyDefintion != null) + { + CMISPropertyAccessor propertyAccessor = null; + if (propertyAccessorMapping != null) + { + propertyAccessor = propertyAccessorMapping.getPropertyAccessor(propertyId); + if (propertyAccessor == null) + { + propertyAccessor = propertyAccessorMapping.createDirectPropertyAccessor(propertyId, + alfrescoPropDef.getName()); + } + } + + CMISPropertyLuceneBuilder luceneBuilder = null; + if (luceneBuilderMapping != null) + { + luceneBuilder = luceneBuilderMapping.getPropertyLuceneBuilder(propertyId); + if (luceneBuilder == null) + { + luceneBuilder = luceneBuilderMapping.createDirectPropertyLuceneBuilder(alfrescoPropDef + .getName()); + } + } + + registerProperty(new BasePropertyDefintionWrapper(propertyDefintion, alfrescoPropDef.getName(), this, + propertyAccessor, luceneBuilder)); + } + } + } + + /** + * Registers a property definition with this type + */ + protected void registerProperty(PropertyDefinitionWrapper propDefWrapper) + { + if (propDefWrapper == null) + { + return; + } + + if (propertiesById.containsKey(propDefWrapper.getPropertyId())) + { + throw new AlfrescoRuntimeException("Property defintion " + propDefWrapper.getPropertyId() + + " already exists on type " + typeDef.getId()); + } + + propertiesById.put(propDefWrapper.getPropertyId(), propDefWrapper); + propertiesByQueryName.put(propDefWrapper.getPropertyDefinition().getQueryName(), propDefWrapper); + propertiesByQName.put(propDefWrapper.getAlfrescoName(), propDefWrapper); + typeDefInclProperties.addPropertyDefinition(propDefWrapper.getPropertyDefinition()); + } + + /** + * Creates a property definition object. + */ + protected PropertyDefinition createPropertyDefinition(CMISMapping cmisMapping, String id, + QName alfrescoPropName, DictionaryService dictionaryService, org.alfresco.service.cmr.dictionary.PropertyDefinition propDef, boolean inherited) + { + PropertyType datatype = cmisMapping.getDataType(propDef.getDataType()); + if (datatype == null) + { + return null; + } + + AbstractPropertyDefinition result = null; + + switch (datatype) + { + case BOOLEAN: + result = new PropertyBooleanDefinitionImpl(); + break; + case DATETIME: + result = new PropertyDateTimeDefinitionImpl(); + break; + case DECIMAL: + result = new PropertyDecimalDefinitionImpl(); + break; + case HTML: + result = new PropertyHtmlDefinitionImpl(); + break; + case ID: + result = new PropertyIdDefinitionImpl(); + break; + case INTEGER: + result = new PropertyIntegerDefinitionImpl(); + break; + case STRING: + result = new PropertyStringDefinitionImpl(); + break; + case URI: + result = new PropertyUriDefinitionImpl(); + break; + default: + throw new RuntimeException("Unknown datatype! Spec change?"); + } + + if (id.equals(PropertyIds.OBJECT_TYPE_ID) || id.equals(PropertyIds.SOURCE_ID) + || id.equals(PropertyIds.TARGET_ID)) + { + // the CMIS spec requirement + result.setUpdatability(Updatability.ONCREATE); + } else + { + result.setUpdatability(propDef.isProtected() ? Updatability.READONLY : Updatability.READWRITE); + } + + result.setId(id); + result.setLocalName(alfrescoPropName.getLocalName()); + result.setLocalNamespace(alfrescoPropName.getNamespaceURI()); + result.setDisplayName(null); + result.setDescription(null); + result.setPropertyType(datatype); + result.setCardinality(propDef.isMultiValued() ? Cardinality.MULTI : Cardinality.SINGLE); + result.setIsInherited(inherited); + result.setIsRequired(propDef.isMandatory()); + addDefaultValue(propDef.getDefaultValue(), result); + + // query and order + result.setQueryName(ISO9075.encodeSQL(cmisMapping.buildPrefixEncodedString(alfrescoPropName))); + result.setIsQueryable(propDef.isIndexed()); + result.setIsOrderable(false); + + if (result.isQueryable()) + { + if (result.getCardinality() == Cardinality.SINGLE) + { + IndexTokenisationMode indexTokenisationMode = IndexTokenisationMode.TRUE; + if (propDef.getIndexTokenisationMode() != null) + { + indexTokenisationMode = propDef.getIndexTokenisationMode(); + } + + switch (indexTokenisationMode) + { + case BOTH: + case FALSE: + result.setIsOrderable(true); + break; + case TRUE: + default: + if (propDef.getDataType().getName().equals(DataTypeDefinition.BOOLEAN) + || propDef.getDataType().getName().equals(DataTypeDefinition.DATE) + || propDef.getDataType().getName().equals(DataTypeDefinition.DATETIME) + || propDef.getDataType().getName().equals(DataTypeDefinition.DOUBLE) + || propDef.getDataType().getName().equals(DataTypeDefinition.FLOAT) + || propDef.getDataType().getName().equals(DataTypeDefinition.INT) + || propDef.getDataType().getName().equals(DataTypeDefinition.LONG) + || propDef.getDataType().getName().equals(DataTypeDefinition.PATH) + ) + { + result.setIsOrderable(true); + } + } + } + } + + // MNT-9089 fix, set min/max values for numeric properties + // MNT-11304 fix, use default boundaries only for numeric types + if (result instanceof PropertyIntegerDefinitionImpl) + { + if (propDef.getDataType().getName().equals(DataTypeDefinition.INT)) + { + ((PropertyIntegerDefinitionImpl) result).setMinValue(BigInteger.valueOf(Integer.MIN_VALUE)); + ((PropertyIntegerDefinitionImpl) result).setMaxValue(BigInteger.valueOf(Integer.MAX_VALUE)); + } + if (propDef.getDataType().getName().equals(DataTypeDefinition.LONG)) + { + ((PropertyIntegerDefinitionImpl) result).setMinValue(BigInteger.valueOf(Long.MIN_VALUE)); + ((PropertyIntegerDefinitionImpl) result).setMaxValue(BigInteger.valueOf(Long.MAX_VALUE)); + } + } + // end MNT-9089 + + // constraints and choices + for (ConstraintDefinition constraintDef : propDef.getConstraints()) + { + Constraint constraint = constraintDef.getConstraint(); + if (constraint instanceof ListOfValuesConstraint) + { + addChoiceList((ListOfValuesConstraint) constraint, result); + } + + if ((constraint instanceof StringLengthConstraint) && (result instanceof PropertyStringDefinitionImpl)) + { + StringLengthConstraint slc = (StringLengthConstraint) constraint; + ((PropertyStringDefinitionImpl) result).setMaxLength(BigInteger.valueOf(slc.getMaxLength())); + } + + if (constraint instanceof NumericRangeConstraint) + { + NumericRangeConstraint nrc = (NumericRangeConstraint) constraint; + if (result instanceof PropertyIntegerDefinitionImpl) + { + ((PropertyIntegerDefinitionImpl) result) + .setMinValue(BigInteger.valueOf(((Double) nrc.getMinValue()).longValue())); + ((PropertyIntegerDefinitionImpl) result) + .setMaxValue(BigInteger.valueOf(((Double) nrc.getMaxValue()).longValue())); + } + if (result instanceof PropertyDecimalDefinitionImpl) + { + ((PropertyDecimalDefinitionImpl) result).setMinValue(BigDecimal.valueOf(nrc.getMinValue())); + ((PropertyDecimalDefinitionImpl) result).setMaxValue(BigDecimal.valueOf(nrc.getMaxValue())); + } + } + } + + return result; + } + + protected void createActionEvaluators(PropertyAccessorMapping propertyAccessorMapping, BaseTypeId baseTypeId) + { + if (propertyAccessorMapping != null) + { + actionEvaluators = propertyAccessorMapping.getActionEvaluators(baseTypeId); + } else + { + actionEvaluators = Collections.emptyMap(); + } + } + + @SuppressWarnings("unchecked") + private T convertValueFromString(String value, PropertyType datatype) + { + if (value == null) + { + return null; + } + + try + { + switch (datatype) + { + case BOOLEAN: + return (T) Boolean.valueOf(value); + case DATETIME: + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(ISO8601DateFormat.parse(value)); + return (T) cal; + case DECIMAL: + return (T) new BigDecimal(value); + case HTML: + return (T) value; + case ID: + return (T) value; + case INTEGER: + return (T) new BigInteger(value); + case STRING: + return (T) value; + case URI: + return (T) value; + default: ; + } + } + catch (Exception e) + { + logger.error("Failed to convert value " + value + " to " + datatype, e); + return null; + } + + throw new RuntimeException("Unknown datatype! Spec change?"); + } + + /** + * Adds the default value to a property definition. + */ + private void addDefaultValue(String value, PropertyDefinition propDef) + { + if (value == null) + { + return; + } + + if (propDef instanceof PropertyBooleanDefinitionImpl) + { + PropertyBooleanDefinitionImpl propDefImpl = (PropertyBooleanDefinitionImpl) propDef; + propDefImpl.setDefaultValue(Collections.singletonList((Boolean) convertValueFromString(value, + PropertyType.BOOLEAN))); + } else if (propDef instanceof PropertyDateTimeDefinitionImpl) + { + PropertyDateTimeDefinitionImpl propDefImpl = (PropertyDateTimeDefinitionImpl) propDef; + propDefImpl.setDefaultValue(Collections.singletonList((GregorianCalendar) convertValueFromString(value, + PropertyType.DATETIME))); + } else if (propDef instanceof PropertyDecimalDefinitionImpl) + { + PropertyDecimalDefinitionImpl propDefImpl = (PropertyDecimalDefinitionImpl) propDef; + propDefImpl.setDefaultValue(Collections.singletonList((BigDecimal) convertValueFromString(value, + PropertyType.DECIMAL))); + } else if (propDef instanceof PropertyHtmlDefinitionImpl) + { + PropertyHtmlDefinitionImpl propDefImpl = (PropertyHtmlDefinitionImpl) propDef; + propDefImpl.setDefaultValue(Collections.singletonList((String) convertValueFromString(value, + PropertyType.HTML))); + } else if (propDef instanceof PropertyIdDefinitionImpl) + { + PropertyIdDefinitionImpl propDefImpl = (PropertyIdDefinitionImpl) propDef; + propDefImpl.setDefaultValue(Collections.singletonList((String) convertValueFromString(value, + PropertyType.ID))); + } else if (propDef instanceof PropertyIntegerDefinitionImpl) + { + PropertyIntegerDefinitionImpl propDefImpl = (PropertyIntegerDefinitionImpl) propDef; + propDefImpl.setDefaultValue(Collections.singletonList((BigInteger) convertValueFromString(value, + PropertyType.INTEGER))); + } else if (propDef instanceof PropertyStringDefinitionImpl) + { + PropertyStringDefinitionImpl propDefImpl = (PropertyStringDefinitionImpl) propDef; + propDefImpl.setDefaultValue(Collections.singletonList((String) convertValueFromString(value, + PropertyType.STRING))); + } else if (propDef instanceof PropertyUriDefinitionImpl) + { + PropertyUriDefinitionImpl propDefImpl = (PropertyUriDefinitionImpl) propDef; + propDefImpl.setDefaultValue(Collections.singletonList((String) convertValueFromString(value, + PropertyType.URI))); + } + } + + /** + * Adds choices to the property defintion. + */ + private void addChoiceList(ListOfValuesConstraint lovc, PropertyDefinition propDef) + { + if (propDef instanceof PropertyBooleanDefinitionImpl) + { + PropertyBooleanDefinitionImpl propDefImpl = (PropertyBooleanDefinitionImpl) propDef; + propDefImpl.setIsOpenChoice(false); + + List> choiceList = new ArrayList>(); + for (String allowed : lovc.getAllowedValues()) + { + ChoiceImpl choice = new ChoiceImpl(); + choice.setDisplayName(allowed); + choice.setValue(Collections.singletonList((Boolean) convertValueFromString(allowed, + PropertyType.BOOLEAN))); + + choiceList.add(choice); + } + + propDefImpl.setChoices(choiceList); + } else if (propDef instanceof PropertyDateTimeDefinitionImpl) + { + PropertyDateTimeDefinitionImpl propDefImpl = (PropertyDateTimeDefinitionImpl) propDef; + propDefImpl.setIsOpenChoice(false); + + List> choiceList = new ArrayList>(); + for (String allowed : lovc.getAllowedValues()) + { + ChoiceImpl choice = new ChoiceImpl(); + choice.setDisplayName(allowed); + choice.setValue(Collections.singletonList((GregorianCalendar) convertValueFromString(allowed, + PropertyType.DATETIME))); + + choiceList.add(choice); + } + + propDefImpl.setChoices(choiceList); + } else if (propDef instanceof PropertyDecimalDefinitionImpl) + { + PropertyDecimalDefinitionImpl propDefImpl = (PropertyDecimalDefinitionImpl) propDef; + propDefImpl.setIsOpenChoice(false); + + List> choiceList = new ArrayList>(); + for (String allowed : lovc.getAllowedValues()) + { + ChoiceImpl choice = new ChoiceImpl(); + choice.setDisplayName(allowed); + choice.setValue(Collections.singletonList((BigDecimal) convertValueFromString(allowed, + PropertyType.DECIMAL))); + + choiceList.add(choice); + } + + propDefImpl.setChoices(choiceList); + } else if (propDef instanceof PropertyHtmlDefinitionImpl) + { + PropertyHtmlDefinitionImpl propDefImpl = (PropertyHtmlDefinitionImpl) propDef; + propDefImpl.setIsOpenChoice(false); + + List> choiceList = new ArrayList>(); + for (String allowed : lovc.getAllowedValues()) + { + ChoiceImpl choice = new ChoiceImpl(); + choice.setDisplayName(allowed); + choice.setValue(Collections.singletonList((String) convertValueFromString(allowed, PropertyType.HTML))); + + choiceList.add(choice); + } + + propDefImpl.setChoices(choiceList); + } else if (propDef instanceof PropertyIdDefinitionImpl) + { + PropertyIdDefinitionImpl propDefImpl = (PropertyIdDefinitionImpl) propDef; + propDefImpl.setIsOpenChoice(false); + + List> choiceList = new ArrayList>(); + for (String allowed : lovc.getAllowedValues()) + { + ChoiceImpl choice = new ChoiceImpl(); + choice.setDisplayName(allowed); + choice.setValue(Collections.singletonList((String) convertValueFromString(allowed, PropertyType.ID))); + + choiceList.add(choice); + } + + propDefImpl.setChoices(choiceList); + } else if (propDef instanceof PropertyIntegerDefinitionImpl) + { + PropertyIntegerDefinitionImpl propDefImpl = (PropertyIntegerDefinitionImpl) propDef; + propDefImpl.setIsOpenChoice(false); + + List> choiceList = new ArrayList>(); + for (String allowed : lovc.getAllowedValues()) + { + ChoiceImpl choice = new ChoiceImpl(); + choice.setDisplayName(allowed); + choice.setValue(Collections.singletonList((BigInteger) convertValueFromString(allowed, + PropertyType.INTEGER))); + + choiceList.add(choice); + } + + propDefImpl.setChoices(choiceList); + } else if (propDef instanceof PropertyStringDefinitionImpl) + { + PropertyStringDefinitionImpl propDefImpl = (PropertyStringDefinitionImpl) propDef; + propDefImpl.setIsOpenChoice(false); + + List> choiceList = new ArrayList>(); + for (String allowed : lovc.getAllowedValues()) + { + ChoiceImpl choice = new ChoiceImpl(); + choice.setDisplayName(allowed); + choice.setValue(Collections + .singletonList((String) convertValueFromString(allowed, PropertyType.STRING))); + + choiceList.add(choice); + } + + propDefImpl.setChoices(choiceList); + } else if (propDef instanceof PropertyUriDefinitionImpl) + { + PropertyUriDefinitionImpl propDefImpl = (PropertyUriDefinitionImpl) propDef; + propDefImpl.setIsOpenChoice(false); + + List> choiceList = new ArrayList>(); + for (String allowed : lovc.getAllowedValues()) + { + ChoiceImpl choice = new ChoiceImpl(); + choice.setDisplayName(allowed); + choice.setValue(Collections.singletonList((String) convertValueFromString(allowed, PropertyType.URI))); + + choiceList.add(choice); + } + + propDefImpl.setChoices(choiceList); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/BasePropertyDefintionWrapper.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/BasePropertyDefintionWrapper.java new file mode 100644 index 0000000000..b96b166c4c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/BasePropertyDefintionWrapper.java @@ -0,0 +1,89 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.io.Serializable; + +import org.alfresco.service.namespace.QName; +import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition; + +public class BasePropertyDefintionWrapper implements PropertyDefinitionWrapper, Serializable +{ + private static final long serialVersionUID = 1L; + + private PropertyDefinition propDef; + private QName alfrescoName; + private TypeDefinitionWrapper owningType; + private CMISPropertyAccessor accessor; + private CMISPropertyLuceneBuilder luceneBuilder; + + public BasePropertyDefintionWrapper(PropertyDefinition propDef, QName alfrescoName, + TypeDefinitionWrapper owningType, CMISPropertyAccessor accessor, CMISPropertyLuceneBuilder luceneBuilder) + { + this.propDef = propDef; + this.alfrescoName = alfrescoName; + this.owningType = owningType; + this.accessor = accessor; + this.luceneBuilder = luceneBuilder; + } + + @Override + public PropertyDefinition getPropertyDefinition() + { + return propDef; + } + + @Override + public String getPropertyId() + { + return propDef.getId(); + } + + @Override + public QName getAlfrescoName() + { + return alfrescoName; + } + + @Override + public TypeDefinitionWrapper getOwningType() + { + return owningType; + } + + @Override + public CMISPropertyAccessor getPropertyAccessor() + { + return accessor; + } + + @Override + public CMISPropertyLuceneBuilder getPropertyLuceneBuilder() + { + return luceneBuilder; + } + +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISAbstractDictionaryService.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISAbstractDictionaryService.java new file mode 100644 index 0000000000..89e329704c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISAbstractDictionaryService.java @@ -0,0 +1,505 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; + +import org.alfresco.opencmis.mapping.CMISMapping; +import org.alfresco.repo.cache.SimpleCache; +import org.alfresco.repo.dictionary.CompiledModel; +import org.alfresco.repo.dictionary.DictionaryDAO; +import org.alfresco.repo.dictionary.ExtendedDictionaryListener; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ISO9075; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.chemistry.opencmis.commons.enums.PropertyType; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.ApplicationEvent; +import org.springframework.extensions.surf.util.AbstractLifecycleBean; + +/** + * Common CMIS Dictionary Support including registry of Types. + * + * @author davidc + * @author florian.mueller + */ +public abstract class CMISAbstractDictionaryService extends AbstractLifecycleBean implements CMISDictionaryService, + ExtendedDictionaryListener +{ + // Logger + protected static final Log logger = LogFactory.getLog(CMISAbstractDictionaryService.class); + + // service dependencies + protected DictionaryDAO dictionaryDAO; + protected DictionaryService dictionaryService; + protected CMISMapping cmisMapping; + protected PropertyAccessorMapping accessorMapping; + protected PropertyLuceneBuilderMapping luceneBuilderMapping; + protected TenantService tenantService; + + private final ReentrantReadWriteLock registryLock = new ReentrantReadWriteLock(); + private final WriteLock registryWriteLock = registryLock.writeLock(); + private final ReadLock registryReadLock = registryLock.readLock(); + + // note: cache is tenant-aware (if using TransctionalCache impl) + private SimpleCache cmisRegistryCache; + private final String KEY_OPENCMIS_DICTIONARY_REGISTRY = "key.openCmisDictionaryRegistry"; + + public void setTenantService(TenantService tenantService) + { + this.tenantService = tenantService; + } + + /** + * Set the mapping service + * + * @param cmisMapping + * CMISMapping + */ + public void setCmisMapping(CMISMapping cmisMapping) + { + this.cmisMapping = cmisMapping; + } + + /** + * Set the property accessor mapping service + * + * @param accessorMapping + * mapping + */ + public void setPropertyAccessorMapping(PropertyAccessorMapping accessorMapping) + { + this.accessorMapping = accessorMapping; + } + + /** + * Set the property lucene mapping service + * + * @param luceneBuilderMapping + * mapping + */ + public void setPropertyLuceneBuilderMapping(PropertyLuceneBuilderMapping luceneBuilderMapping) + { + this.luceneBuilderMapping = luceneBuilderMapping; + } + + /** + * Set the dictionary Service + * + * @param dictionaryService + * DictionaryService + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + /** + * Set the dictionary DAO + * + * @param dictionaryDAO + * DictionaryDAO + */ + public void setDictionaryDAO(DictionaryDAO dictionaryDAO) + { + this.dictionaryDAO = dictionaryDAO; + } + + public void setSingletonCache(SimpleCache singletonCache) + { + this.cmisRegistryCache = singletonCache; + } + + protected interface DictionaryInitializer + { + Collection createDefinitions(CMISDictionaryRegistry cmisRegistry); + + Collection createDefinitions(CMISDictionaryRegistry cmisRegistry, + CompiledModel model); + } + + protected abstract DictionaryInitializer getCoreDictionaryInitializer(); + + protected abstract DictionaryInitializer getTenantDictionaryInitializer(); + + protected CMISDictionaryRegistry getRegistry() + { + String tenant = TenantUtil.getCurrentDomain(); + return getRegistry(tenant); + } + + CMISDictionaryRegistry getRegistry(String tenant) + { + CMISDictionaryRegistry cmisRegistry = null; + + String cacheKey = getCacheKey(tenant); + + registryReadLock.lock(); + try + { + cmisRegistry = cmisRegistryCache.get(cacheKey); + } + finally + { + registryReadLock.unlock(); + } + + if (cmisRegistry == null) + { + cmisRegistry = createDictionaryRegistry(tenant); + + registryWriteLock.lock(); + try + { + cmisRegistryCache.put(cacheKey, cmisRegistry); + } + finally + { + registryWriteLock.unlock(); + } + } + + return cmisRegistry; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.extensions.surf.util.AbstractLifecycleBean# + * onBootstrap (org.springframework.context.ApplicationEvent) + */ + @Override + protected void onBootstrap(ApplicationEvent event) + { + afterDictionaryInit(); + + // TODO revisit (for KS and/or 1.1) + if (dictionaryDAO != null) + { + dictionaryDAO.registerListener(this); + } + else + { + logger.error("DictionaryDAO is null - hence CMIS Dictionary not registered for updates"); + } + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.extensions.surf.util.AbstractLifecycleBean#onShutdown + * (org.springframework.context.ApplicationEvent) + */ + @Override + protected void onShutdown(ApplicationEvent event) + { + } + + private String getCacheKey() + { + String tenant = tenantService.getCurrentUserDomain(); + return getCacheKey(tenant); + } + + private String getCacheKey(String tenant) + { + String cacheKey = KEY_OPENCMIS_DICTIONARY_REGISTRY + "." + tenant + "." + + cmisMapping.getCmisVersion().toString(); + return cacheKey; + } + + protected CMISDictionaryRegistry createCoreDictionaryRegistry() + { + CMISDictionaryRegistryImpl cmisRegistry = new CMISDictionaryRegistryImpl(this, cmisMapping, dictionaryService, + getCoreDictionaryInitializer()); + cmisRegistry.init(); + return cmisRegistry; + } + + protected CMISDictionaryRegistry createTenantDictionaryRegistry(String tenant) + { + CMISDictionaryRegistryImpl cmisRegistry = new CMISDictionaryRegistryImpl(this, tenant, "", cmisMapping, + dictionaryService, getTenantDictionaryInitializer()); + cmisRegistry.init(); + return cmisRegistry; + } + + protected CMISDictionaryRegistry createDictionaryRegistryWithWriteLock() + { + String tenant = TenantUtil.getCurrentDomain(); + CMISDictionaryRegistry cmisRegistry = createDictionaryRegistry(tenant); + String cacheKey = getCacheKey(tenant); + + registryWriteLock.lock(); + try + { + // publish new registry + cmisRegistryCache.put(cacheKey, cmisRegistry); + + } + finally + { + registryWriteLock.unlock(); + } + + return cmisRegistry; + } + + protected CMISDictionaryRegistry createDictionaryRegistry(String tenant) + { + CMISDictionaryRegistry cmisRegistry = null; + + if (tenant.equals(TenantService.DEFAULT_DOMAIN)) + { + cmisRegistry = createCoreDictionaryRegistry(); + } + else + { + cmisRegistry = createTenantDictionaryRegistry(tenant); + } + + return cmisRegistry; + } + + @Override + public TypeDefinitionWrapper findType(String typeId) + { + TypeDefinitionWrapper typeDef = getRegistry().getTypeDefByTypeId(typeId); + if (typeDef != null && typeDef.getTypeDefinition(false).getDisplayName() == null) + { + typeDef.updateDefinition(dictionaryService); + } + return typeDef; + } + + @Override + public boolean isExcluded(QName qname) + { + return cmisMapping.isExcluded(qname); + } + + @Override + public TypeDefinitionWrapper findTypeForClass(QName clazz, BaseTypeId... matchingScopes) + { + // searching for relationship + boolean scopeByRelationship = false; + for (BaseTypeId scope : matchingScopes) + { + if (scope == BaseTypeId.CMIS_RELATIONSHIP) + { + scopeByRelationship = true; + break; + } + } + + // locate type in registry + clazz = cmisMapping.getCmisType(clazz); + TypeDefinitionWrapper typeDef = null; + if (scopeByRelationship) + { + typeDef = getRegistry().getAssocDefByQName(clazz); + } + else + { + typeDef = getRegistry().getTypeDefByQName(clazz); + if (typeDef == null) + { + typeDef = getRegistry().getAssocDefByQName(clazz); + } + } + + // ensure matches one of provided matching scopes + TypeDefinitionWrapper matchingTypeDef = (matchingScopes.length == 0) ? typeDef : null; + if (typeDef != null) + { + for (BaseTypeId scope : matchingScopes) + { + if (typeDef.getBaseTypeId() == scope) + { + matchingTypeDef = typeDef; + break; + } + } + } + + return matchingTypeDef; + } + + @Override + public TypeDefinitionWrapper findNodeType(QName clazz) + { + return getRegistry().getTypeDefByQName(cmisMapping.getCmisType(clazz)); + } + + @Override + public TypeDefinitionWrapper findAssocType(QName clazz) + { + return getRegistry().getAssocDefByQName(cmisMapping.getCmisType(clazz)); + } + + @Override + public TypeDefinitionWrapper findTypeByQueryName(String queryName) + { + // ISO 9075 name look up should be lower case. + return getRegistry().getTypeDefByQueryName(ISO9075.lowerCaseEncodedSQL(queryName)); + } + + @Override + public PropertyDefinitionWrapper findProperty(String propId) + { + return getRegistry().getPropDefByPropId(propId); + } + + @Override + public PropertyDefinitionWrapper findPropertyByQueryName(String queryName) + { + return getRegistry().getPropDefByQueryName(ISO9075.lowerCaseEncodedSQL(queryName)); + } + + @Override + public List getBaseTypes() + { + return getBaseTypes(true); + } + + @Override + public List getBaseTypes(boolean includeParent) + { + List types = getRegistry().getBaseTypes(includeParent); + + for (TypeDefinitionWrapper typeDef : types) + { + if (typeDef != null && typeDef.getTypeDefinition(false).getDisplayName() == null) + { + typeDef.updateDefinition(dictionaryService); + } + } + + return Collections.unmodifiableList(types); + } + + @Override + public List getAllTypes() + { + // TODO is there a way of not having to reconstruct this every time? + return Collections.unmodifiableList(new ArrayList(getRegistry().getTypeDefs())); + } + + @Override + public List getAllTypes(boolean includeParent) + { + // TODO is there a way of not having to reconstruct this every time? + return Collections + .unmodifiableList(new ArrayList(getRegistry().getTypeDefs(includeParent))); + } + + @Override + public PropertyType findDataType(QName dataType) + { + return cmisMapping.getDataType(dataType); + } + + @Override + public QName findAlfrescoDataType(PropertyType propertyType) + { + return cmisMapping.getAlfrescoDataType(propertyType); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.dictionary.DictionaryListener#onInit() + */ + @Override + public void onDictionaryInit() + { + } + + @Override + public void modelAdded(CompiledModel model, String tenantDomain) + { + getRegistry(tenantDomain).addModel(model); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.dictionary.DictionaryListener#afterInit() + */ + @Override + public void afterDictionaryInit() + { + createDictionaryRegistryWithWriteLock(); + } + + /* + * (non-Javadoc) + * + * @see + * org.alfresco.repo.dictionary.DictionaryListener#afterDictionaryDestroy() + */ + @Override + public void afterDictionaryDestroy() + { + registryWriteLock.lock(); + try + { + String cacheKey = getCacheKey(); + cmisRegistryCache.remove(cacheKey); + } + finally + { + registryWriteLock.unlock(); + } + } + + @Override + public List getChildren(String typeId) + { + List children = getRegistry().getChildren(typeId); + + for (TypeDefinitionWrapper child : children) + { + if (child != null && child.getTypeDefinition(false).getDisplayName() == null) + { + child.updateDefinition(dictionaryService); + } + } + + return children; + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISActionEvaluator.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISActionEvaluator.java new file mode 100644 index 0000000000..3936234e20 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISActionEvaluator.java @@ -0,0 +1,46 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import org.apache.chemistry.opencmis.commons.enums.Action; + +public interface CMISActionEvaluator +{ + /** + * Gets the CMIS Allowed Action + * + * @return Action + */ + public Action getAction(); + + /** + * Determines if an action is allowed on an object + * + * @param nodeInfo CMISNodeInfo + * @return boolean + */ + public boolean isAllowed(CMISNodeInfo nodeInfo); +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryRegistry.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryRegistry.java new file mode 100644 index 0000000000..eb3e98c1d1 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryRegistry.java @@ -0,0 +1,63 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.Collection; +import java.util.List; + +import org.alfresco.repo.dictionary.CompiledModel; +import org.alfresco.service.namespace.QName; + +/** + * + * @author sglover + * + */ +public interface CMISDictionaryRegistry +{ + TypeDefinitionWrapper getTypeDefByTypeId(String typeId); + TypeDefinitionWrapper getTypeDefByTypeId(String typeId, boolean includeParent); + TypeDefinitionWrapper getAssocDefByQName(QName qname); + TypeDefinitionWrapper getTypeDefByQueryName(Object queryName); + TypeDefinitionWrapper getTypeDefByQName(QName qname); + PropertyDefinitionWrapper getPropDefByPropId(String propId); + PropertyDefinitionWrapper getPropDefByQueryName(Object queryName); + List getBaseTypes(); + List getBaseTypes(boolean includeParent); + Collection getTypeDefs(); + Collection getTypeDefs(boolean includeParent); + Collection getAssocDefs(); + Collection getAssocDefs(boolean includeParent); + void registerTypeDefinition(AbstractTypeDefinitionWrapper typeDef); + String getTenant(); + List getChildren(String typeId); + void setChildren(String typeId, List children); + void addChild(String typeId, TypeDefinitionWrapper child); + + void addModel(CompiledModel model); + void updateModel(CompiledModel model); + void removeModel(CompiledModel model); +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryRegistryImpl.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryRegistryImpl.java new file mode 100644 index 0000000000..26c4dfc8dd --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryRegistryImpl.java @@ -0,0 +1,537 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.alfresco.opencmis.dictionary.CMISAbstractDictionaryService.DictionaryInitializer; +import org.alfresco.opencmis.mapping.CMISMapping; +import org.alfresco.repo.dictionary.CompiledModel; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.namespace.QName; +import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.CmisExtensionElementImpl; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * CMIS Dictionary registry + * + * Index of CMIS Type Definitions + * + * @author sglover + */ +public class CMISDictionaryRegistryImpl implements CMISDictionaryRegistry +{ + public static final String ALFRESCO_EXTENSION_NAMESPACE = "http://www.alfresco.org"; + public static final String MANDATORY_ASPECTS = "mandatoryAspects"; + public static final String MANDATORY_ASPECT = "mandatoryAspect"; + + // Logger + protected static final Log logger = LogFactory.getLog(CMISDictionaryRegistryImpl.class); + + private CMISMapping cmisMapping; + private DictionaryService dictionaryService; + private String tenant; + + protected CMISAbstractDictionaryService cmisDictionaryService; + private String parentTenant; + + private DictionaryInitializer dictionaryInitializer; + + // Type Definitions Index + private Map typeDefsByQName = new HashMap(); + private Map assocDefsByQName = new HashMap(); + + private Map typeDefsByTypeId = new HashMap(); + private Map typeDefsByQueryName = new HashMap(); + private List baseTypes = new ArrayList(); + + private Map propDefbyPropId = new HashMap(); + private Map propDefbyQueryName = new HashMap(); + + private Map> children = new HashMap>(); + + public CMISDictionaryRegistryImpl(CMISAbstractDictionaryService cmisDictionaryService, CMISMapping cmisMapping, + DictionaryService dictionaryService, DictionaryInitializer dictionaryInitializer) + { + this(cmisDictionaryService, "", null, cmisMapping, dictionaryService, dictionaryInitializer); + } + + /* + * Testing only. + */ + CMISDictionaryRegistryImpl() + { + } + + public CMISDictionaryRegistryImpl(CMISAbstractDictionaryService cmisDictionaryService, String tenant, String parentTenant, + CMISMapping cmisMapping, DictionaryService dictionaryService, DictionaryInitializer dictionaryInitializer) + { + this.cmisDictionaryService = cmisDictionaryService; + this.tenant = tenant; + this.parentTenant = parentTenant; + this.cmisMapping = cmisMapping; + this.dictionaryService = dictionaryService; + this.dictionaryInitializer = dictionaryInitializer; + } + + protected CMISDictionaryRegistry getParent() + { + CMISDictionaryRegistry registry = null; + if(parentTenant != null) + { + return cmisDictionaryService.getRegistry(parentTenant); + } + return registry; + } + + @Override + public String getTenant() + { + return tenant; + } + + private List getChildrenImpl(String typeId) + { + return children.get(typeId); + } + + @Override + public List getChildren(String typeId) + { + List ret = new LinkedList<>(); + + List children = getChildrenImpl(typeId); + if(children != null) + { + ret.addAll(children); + } + + if(getParent() != null) + { + children = getParent().getChildren(typeId); + if(children != null) + { + ret.addAll(children); + } + } + + return ret; + } + + @Override + public void setChildren(String typeId, List children) + { + this.children.put(typeId, children); + } + + @Override + public void addChild(String typeId, TypeDefinitionWrapper child) + { + List children = this.children.get(typeId); + if(children == null) + { + children = new LinkedList(); + this.children.put(typeId, children); + } + children.add(child); + } + + @Override + public TypeDefinitionWrapper getTypeDefByTypeId(String typeId) + { + return getTypeDefByTypeId(typeId, true); + } + + @Override + public TypeDefinitionWrapper getTypeDefByTypeId(String typeId, boolean includeParent) + { + TypeDefinitionWrapper typeDef = typeDefsByTypeId.get(typeId); + if(typeDef == null && includeParent && getParent() != null) + { + typeDef = getParent().getTypeDefByTypeId(typeId); + } + + return typeDef; + } + + @Override + public TypeDefinitionWrapper getAssocDefByQName(QName qname) + { + TypeDefinitionWrapper typeDef = assocDefsByQName.get(qname); + if(typeDef == null && getParent() != null) + { + typeDef = getParent().getAssocDefByQName(qname); + } + + return typeDef; + } + + @Override + public TypeDefinitionWrapper getTypeDefByQueryName(Object queryName) + { + TypeDefinitionWrapper typeDef = typeDefsByQueryName.get(queryName); + if(typeDef == null && getParent() != null) + { + typeDef = getParent().getTypeDefByQueryName(queryName); + } + + return typeDef; + } + + @Override + public TypeDefinitionWrapper getTypeDefByQName(QName qname) + { + TypeDefinitionWrapper typeDef = typeDefsByQName.get(qname); + if(typeDef == null && getParent() != null) + { + typeDef = getParent().getTypeDefByQName(qname); + } + + return typeDef; + } + + @Override + public PropertyDefinitionWrapper getPropDefByPropId(String propId) + { + PropertyDefinitionWrapper propDef = propDefbyPropId.get(propId); + if(propDef == null && getParent() != null) + { + propDef = getParent().getPropDefByPropId(propId); + } + + return propDef; + } + + @Override + public PropertyDefinitionWrapper getPropDefByQueryName(Object queryName) + { + PropertyDefinitionWrapper propDef = propDefbyQueryName.get(queryName); + if(propDef == null && getParent() != null) + { + propDef = getParent().getPropDefByQueryName(queryName); + } + + return propDef; + } + + private Collection getTypeDefsImpl() + { + return typeDefsByTypeId.values(); + } + + @Override + public Collection getTypeDefs() + { + return getTypeDefs(true); + } + + @Override + public Collection getTypeDefs(boolean includeParent) + { + Collection ret = new LinkedList<>(); + ret.addAll(getTypeDefsImpl()); + if(includeParent && getParent() != null) + { + ret.addAll(getParent().getTypeDefs()); + } + return Collections.unmodifiableCollection(ret); + } + + private Collection getAssocDefsImpl() + { + return assocDefsByQName.values(); + } + + @Override + public Collection getAssocDefs() + { + return getAssocDefs(true); + } + + @Override + public Collection getAssocDefs(boolean includeParent) + { + Collection ret = new LinkedList<>(); + ret.addAll(getAssocDefsImpl()); + if(includeParent && getParent() != null) + { + ret.addAll(getParent().getAssocDefs()); + } + return Collections.unmodifiableCollection(ret); + } + + private void addTypeExtensions(TypeDefinitionWrapper td) + { + QName classQName = td.getAlfrescoClass(); + ClassDefinition classDef = dictionaryService.getClass(classQName); + if(classDef != null) + { + // add mandatory/default aspects + List defaultAspects = classDef.getDefaultAspects(true); + if(defaultAspects != null && defaultAspects.size() > 0) + { + List mandatoryAspectsExtensions = new ArrayList(); + for(AspectDefinition aspectDef : defaultAspects) + { + QName aspectQName = aspectDef.getName(); + + TypeDefinitionWrapper aspectType = getTypeDefByQName(cmisMapping.getCmisType(aspectQName)); + if (aspectType == null) + { + continue; + } + + mandatoryAspectsExtensions.add(new CmisExtensionElementImpl(ALFRESCO_EXTENSION_NAMESPACE, MANDATORY_ASPECT, null, aspectType.getTypeId())); + } + + if(!mandatoryAspectsExtensions.isEmpty()) + { + td.getTypeDefinition(true).setExtensions( + Collections.singletonList((CmisExtensionElement) new CmisExtensionElementImpl( + ALFRESCO_EXTENSION_NAMESPACE, MANDATORY_ASPECTS, null, mandatoryAspectsExtensions))); + } + } + } + } + + @Override + public void addModel(CompiledModel model) + { + Collection types = dictionaryInitializer.createDefinitions(this, model); + addTypes(types); + for(AbstractTypeDefinitionWrapper type : types) + { + type.resolveInheritance(cmisMapping, this, dictionaryService); + } + } + + @Override + public void updateModel(CompiledModel model) + { + // TODO + } + + @Override + public void removeModel(CompiledModel model) + { + // TODO + } + + private void clear() + { + typeDefsByQName.clear(); + assocDefsByQName.clear(); + typeDefsByTypeId.clear(); + typeDefsByQueryName.clear(); + baseTypes.clear(); + + propDefbyPropId.clear(); + propDefbyQueryName.clear(); + + children.clear(); + } + + private void addTypes(Collection types) + { + // phase 1: construct type definitions and link them together + for (AbstractTypeDefinitionWrapper objectTypeDef : types) + { + List children = objectTypeDef.connectParentAndSubTypes(cmisMapping, this, dictionaryService); + setChildren(objectTypeDef.getTypeId(), children); + } + + // phase 2: register base types and inherit property definitions + for (AbstractTypeDefinitionWrapper typeDef : types) + { + if (typeDef.getTypeDefinition(false).getParentTypeId() == null || + !tenant.equals(TenantService.DEFAULT_DOMAIN)) + { + if(tenant.equals(TenantService.DEFAULT_DOMAIN)) + { + baseTypes.add(typeDef); + } + typeDef.resolveInheritance(cmisMapping, this, dictionaryService); + } + } + + // phase 3: register properties + for (AbstractTypeDefinitionWrapper typeDef : types) + { + registerPropertyDefinitions(typeDef); + } + + // phase 4: assert valid + for (AbstractTypeDefinitionWrapper typeDef : types) + { + typeDef.assertComplete(); + + addTypeExtensions(typeDef); + } + } + + public void init() + { + long start = System.currentTimeMillis(); + + if (logger.isDebugEnabled()) + { + logger.debug("Creating type definitions..."); + } + + Collection types = dictionaryInitializer.createDefinitions(this); + addTypes(types); + + long end = System.currentTimeMillis(); + + if (logger.isInfoEnabled()) + { + logger.info("Initialized CMIS Dictionary " + cmisMapping.getCmisVersion() + " tenant " + tenant + " in " + (end - start) + "ms. Types:" + + typeDefsByTypeId.size() + ", Base Types:" + baseTypes.size()); + } + } + + private List getBaseTypesImpl() + { + return baseTypes; + } + + @Override + public List getBaseTypes() + { + return getBaseTypes(true); + } + + @Override + public List getBaseTypes(boolean includeParent) + { + List ret = new LinkedList(); + + List baseTypes = getBaseTypesImpl(); + if(baseTypes != null) + { + ret.addAll(baseTypes); + } + + if(includeParent && getParent() != null) + { + baseTypes = getParent().getBaseTypes(); + if(baseTypes != null) + { + ret.addAll(baseTypes); + } + } + + return Collections.unmodifiableList(ret); + } + + /** + * Register type definition. + * + * @param typeDef AbstractTypeDefinitionWrapper + */ + @Override + public void registerTypeDefinition(AbstractTypeDefinitionWrapper typeDef) + { + TypeDefinitionWrapper existingTypeDef = typeDefsByTypeId.get(typeDef.getTypeId()); + if (existingTypeDef != null) + { +// throw new AlfrescoRuntimeException("Type " + typeDef.getTypeId() + " already registered"); + if(logger.isWarnEnabled()) + { + logger.warn("Type " + typeDef.getTypeId() + " already registered"); + } + } + + typeDefsByTypeId.put(typeDef.getTypeId(), typeDef); + QName typeQName = typeDef.getAlfrescoName(); + if (typeQName != null) + { + if ((typeDef instanceof RelationshipTypeDefintionWrapper) && !typeDef.isBaseType()) + { + assocDefsByQName.put(typeQName, typeDef); + } else + { + typeDefsByQName.put(typeQName, typeDef); + } + } + + typeDefsByQueryName.put(typeDef.getTypeDefinition(false).getQueryName(), typeDef); + + if (logger.isDebugEnabled()) + { + logger.debug("Registered type " + typeDef.getTypeId() + " (scope=" + typeDef.getBaseTypeId() + ")"); + logger.debug(" QName: " + typeDef.getAlfrescoName()); + logger.debug(" Table: " + typeDef.getTypeDefinition(false).getQueryName()); + logger.debug(" Action Evaluators: " + typeDef.getActionEvaluators().size()); + } + } + + /** + * Register property definitions. + * + * @param typeDef AbstractTypeDefinitionWrapper + */ + public void registerPropertyDefinitions(AbstractTypeDefinitionWrapper typeDef) + { + for (PropertyDefinitionWrapper propDef : typeDef.getProperties(false)) + { + if (propDef.getPropertyDefinition().isInherited()) + { + continue; + } + + propDefbyPropId.put(propDef.getPropertyId(), propDef); + propDefbyQueryName.put(propDef.getPropertyDefinition().getQueryName(), propDef); + } + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("DictionaryRegistry["); + builder.append("Types=").append(typeDefsByTypeId.size()).append(", "); + builder.append("Base Types=").append(baseTypes.size()).append(", "); + builder.append("]"); + return builder.toString(); + } +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryService.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryService.java new file mode 100644 index 0000000000..ecdf9abe60 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISDictionaryService.java @@ -0,0 +1,103 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.List; + +import org.alfresco.service.namespace.QName; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.chemistry.opencmis.commons.enums.PropertyType; + +/** + * Service to query the CMIS meta model + * + * @author davidc + */ +public interface CMISDictionaryService +{ + /** + * Find type for type id + * + * @param typeId String + * @return TypeDefinitionWrapper + */ + TypeDefinitionWrapper findType(String typeId); + + List getChildren(String typeId); + + /** + * Find type for Alfresco class name. Optionally, constrain match to one of + * specified CMIS scopes + * + * @param clazz QName + * @param matchingScopes BaseTypeId... + * @return TypeDefinitionWrapper + */ + TypeDefinitionWrapper findTypeForClass(QName clazz, BaseTypeId... matchingScopes); + + TypeDefinitionWrapper findNodeType(QName clazz); + + TypeDefinitionWrapper findAssocType(QName clazz); + + PropertyDefinitionWrapper findProperty(String propId); + + PropertyDefinitionWrapper findPropertyByQueryName(String queryName); + + /** + * Find a type by its query name + * + * @param queryName String + * @return TypeDefinitionWrapper + */ + TypeDefinitionWrapper findTypeByQueryName(String queryName); + + /** + * Get Base Types + */ + List getBaseTypes(); + + List getBaseTypes(boolean includeParent); + + /** + * Get all Types + * + */ + List getAllTypes(); + + List getAllTypes(boolean includeParent); + + /** + * Find data type + * + * @param dataType QName + * @return PropertyType + */ + PropertyType findDataType(QName dataType); + + QName findAlfrescoDataType(PropertyType propertyType); + + boolean isExcluded(QName qname); +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISNodeInfo.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISNodeInfo.java new file mode 100644 index 0000000000..29f2faaad7 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISNodeInfo.java @@ -0,0 +1,104 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; + +public interface CMISNodeInfo +{ + String getObjectId(); + + CMISObjectVariant getObjectVariant(); + + boolean isVariant(CMISObjectVariant var); + + NodeRef getNodeRef(); + + String getCurrentNodeId(); + + NodeRef getCurrentNodeNodeRef(); + + String getCurrentObjectId(); + + boolean isCurrentVersion(); + + boolean isPWC(); + + boolean hasPWC(); + + boolean isVersion(); + + boolean isLatestVersion(); + + boolean isLatestMajorVersion(); + + boolean isMajorVersion(); + + String getVersionLabel(); + + String getCheckinComment(); + + AssociationRef getAssociationRef(); + + TypeDefinitionWrapper getType(); + + boolean isFolder(); + + boolean isRootFolder(); + + boolean isDocument(); + + boolean isRelationship(); + + boolean isItem(); + + String getName(); + + String getPath(); + + Serializable getCreationDate(); + + Serializable getModificationDate(); + + Serializable getPropertyValue(String id); + + boolean containsPropertyValue(String id); + + void putPropertyValue(String id, Serializable value); + + List getParents(); + + Map getNodeProps(); + + Set getNodeAspects(); +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISObjectVariant.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISObjectVariant.java new file mode 100644 index 0000000000..cb0442f3bb --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISObjectVariant.java @@ -0,0 +1,41 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +public enum CMISObjectVariant +{ + INVALID_ID, // not a valid object id + NOT_EXISTING, // valid id but object doesn't exist + NOT_A_CMIS_OBJECT, // object is not mapped to CMIS + FOLDER, // object is a folder + ITEM, // object is an item + CURRENT_VERSION, // object is a document (current version) + VERSION, // object is a version (not updatable) + PWC, // object is a PWC + ASSOC, // object is a relationship + PERMISSION_DENIED + // user has no permissions +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISPropertyAccessor.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISPropertyAccessor.java new file mode 100644 index 0000000000..c408577ebd --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISPropertyAccessor.java @@ -0,0 +1,80 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.io.Serializable; + +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; + +/** + * CMIS Property Accessor (get and set property values) + * + * @author davidc + */ +public interface CMISPropertyAccessor +{ + /** + * Get the CMIS Property Name + * + * @return String + */ + String getName(); + + /** + * Get the (directly) mapped Alfresco property (if a direct mapping exists) + * + * @return QName + */ + QName getMappedProperty(); + + /** + * Set the property value for a node + * + * @param nodeRef NodeRef + * @param value Serializable + */ + void setValue(NodeRef nodeRef, Serializable value); + + /** + * Get the property value for a node or an association + * + * @param nodeInfo CMISNodeInfo + * @return Serializable + */ + Serializable getValue(CMISNodeInfo nodeInfo); + + /** + * Creates a node info object form the given node ref. + */ + CMISNodeInfo createNodeInfo(NodeRef nodeRef); + + /** + * Creates a node info object form the given association ref. + */ + CMISNodeInfo createNodeInfo(AssociationRef assocRef); +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISPropertyLuceneBuilder.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISPropertyLuceneBuilder.java new file mode 100644 index 0000000000..063af0462d --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISPropertyLuceneBuilder.java @@ -0,0 +1,130 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.io.Serializable; +import java.util.Collection; + +import org.alfresco.repo.search.adaptor.lucene.LuceneFunction; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; + + +/** + * Encapsulate the building of lucene queries for property predicates + */ +public interface CMISPropertyLuceneBuilder +{ + /** + * @param value Serializable + * @param mode PredicateMode + * @param luceneFunction LuceneFunction + * @return the query - may be null if no query is required + * @throws E + */ + public Q buildLuceneEquality(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E; + + /** + * @param not Boolean + * @return the query - may be null if no query is required + * @throws E + */ + public Q buildLuceneExists(LuceneQueryParserAdaptor lqpa, Boolean not) throws E; + + /** + * @param value Serializable + * @param mode PredicateMode + * @param luceneFunction LuceneFunction + * @return the query - may be null if no query is required + * @throws E + */ + public Q buildLuceneGreaterThan(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E; + + /** + * @param value Serializable + * @param mode PredicateMode + * @param luceneFunction LuceneFunction + * @return the query - may be null if no query is required + * @throws E + */ + public Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E; + + /** + * @param not Boolean + * @param mode PredicateMode + * @return the query - may be null if no query is required + * @throws E + */ + public Q buildLuceneIn(LuceneQueryParserAdaptor lqpa, Collection values, Boolean not, PredicateMode mode) throws E; + + /** + * @param value PredicateMode + * @param mode PredicateMode + * @param luceneFunction LuceneFunction + * @return the query - may be null if no query is required + * @throws E + */ + public Q buildLuceneInequality(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E; + + /** + * @param value Serializable + * @param mode PredicateMode + * @param luceneFunction LuceneFunction + * @return the query - may be null if no query is required + * @throws E + */ + public Q buildLuceneLessThan(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E; + + /** + * @param value Serializable + * @param mode PredicateMode + * @param luceneFunction LuceneFunction + * @return the query - may be null if no query is required + * @throws E + */ + public Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E; + + /** + * @param value Serializable + * @param not Boolean + * @return the query - may be null if no query is required + * @throws E + */ + public Q buildLuceneLike(LuceneQueryParserAdaptor lqpa, Serializable value, Boolean not) throws E; + + /** + * @param lqpa TODO + * @return the sort field + * @throws E + */ + public String getLuceneSortField(LuceneQueryParserAdaptor lqpa) throws E; + + /** + * @return the field name + * + */ + public String getLuceneFieldName(); +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISStrictDictionaryService.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISStrictDictionaryService.java new file mode 100644 index 0000000000..610f8a8f5d --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/CMISStrictDictionaryService.java @@ -0,0 +1,319 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.Collection; +import java.util.LinkedList; + +import org.alfresco.opencmis.mapping.CMISMapping; +import org.alfresco.repo.dictionary.CompiledModel; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.QName; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.chemistry.opencmis.commons.enums.CmisVersion; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * CMIS Dictionary which provides Types that strictly conform to the CMIS + * specification. + * + * That is, only maps types to one of root Document, Folder, Relationship and + * Policy. + * + * And Item which is pretty much anything that is not a Document, Folder, Relationship or Policy. + * + * @author steveglover + * @author davidc + * @author mrogers + */ +public class CMISStrictDictionaryService extends CMISAbstractDictionaryService +{ + private Log logger = LogFactory.getLog(CMISStrictDictionaryService.class); + + public static final String DEFAULT = "DEFAULT_DICTIONARY"; + + private DictionaryInitializer coreDictionaryInitializer; + private DictionaryInitializer tenantDictionaryInitializer; + + public void init() + { + this.coreDictionaryInitializer = new DictionaryInitializer() + { + @Override + public Collection createDefinitions(CMISDictionaryRegistry cmisRegistry) + { + Collection ret = new LinkedList<>(); + ret.addAll(createTypeDefs(cmisRegistry, dictionaryService.getAllTypes(true))); + + Collection assocQNames = dictionaryService.getAllAssociations(true); + + // register base type + String typeId = cmisMapping.getCmisTypeId(BaseTypeId.CMIS_RELATIONSHIP, CMISMapping.RELATIONSHIP_QNAME); + ClassDefinition classDef = dictionaryService.getClass(CMISMapping.RELATIONSHIP_QNAME); + + // from Thor + if (classDef == null) + { + if (assocQNames.size() != 0) + { + logger.warn("Unexpected - no class for "+CMISMapping.RELATIONSHIP_QNAME+" - cannot create assocDefs for: "+assocQNames); + } + } + else + { + RelationshipTypeDefintionWrapper objectTypeDef = new RelationshipTypeDefintionWrapper(cmisMapping, + accessorMapping, luceneBuilderMapping, typeId, dictionaryService, classDef); + cmisRegistry.registerTypeDefinition(objectTypeDef); + ret.add(objectTypeDef); + + ret.addAll(createAssocDefs(cmisRegistry, assocQNames)); + } + + ret.addAll(createTypeDefs(cmisRegistry, dictionaryService.getAllAspects(true))); + return ret; + } + + @Override + public Collection createDefinitions(CMISDictionaryRegistry cmisRegistry, + CompiledModel model) + { + Collection ret = new LinkedList<>(); + + model.getClass(model.getTypes().iterator().next().getName()); + + for(TypeDefinition typeDef : model.getTypes()) + { + QName classQName = typeDef.getName(); + AbstractTypeDefinitionWrapper objectTypeDef = createTypeDef(classQName); + if(objectTypeDef != null) + { + cmisRegistry.registerTypeDefinition(objectTypeDef); + ret.add(objectTypeDef); + } + } + + for(AssociationDefinition assocDef : model.getAssociations()) + { + QName classQName = assocDef.getName(); + RelationshipTypeDefintionWrapper assocTypeDef = createAssocDef(classQName); + if(assocTypeDef != null) + { + cmisRegistry.registerTypeDefinition(assocTypeDef); + ret.add(assocTypeDef); + } + } + + for(AspectDefinition aspectDef : model.getAspects()) + { + QName classQName = aspectDef.getName(); + AbstractTypeDefinitionWrapper objectTypeDef = createTypeDef(classQName); + if(objectTypeDef != null) + { + cmisRegistry.registerTypeDefinition(objectTypeDef); + ret.add(objectTypeDef); + } + } + + return ret; + } + }; + + this.tenantDictionaryInitializer = new DictionaryInitializer() + { + @Override + public Collection createDefinitions(CMISDictionaryRegistry cmisRegistry) + { + Collection ret = new LinkedList<>(); + ret.addAll(createTypeDefs(cmisRegistry, dictionaryService.getAllTypes(false))); + ret.addAll(createAssocDefs(cmisRegistry, dictionaryService.getAllAssociations(false))); + ret.addAll(createTypeDefs(cmisRegistry, dictionaryService.getAllAspects(false))); + return ret; + } + + @Override + public Collection createDefinitions(CMISDictionaryRegistry cmisRegistry, + CompiledModel model) + { + Collection ret = new LinkedList<>(); + + for(TypeDefinition typeDef : model.getTypes()) + { + QName classQName = typeDef.getName(); + AbstractTypeDefinitionWrapper objectTypeDef = createTypeDef(classQName); + if(objectTypeDef != null) + { + cmisRegistry.registerTypeDefinition(objectTypeDef); + ret.add(objectTypeDef); + } + } + + for(AssociationDefinition assocDef : model.getAssociations()) + { + QName classQName = assocDef.getName(); + RelationshipTypeDefintionWrapper assocTypeDef = createAssocDef(classQName); + if(assocTypeDef != null) + { + cmisRegistry.registerTypeDefinition(assocTypeDef); + ret.add(assocTypeDef); + } + } + + for(AspectDefinition aspectDef : model.getAspects()) + { + QName classQName = aspectDef.getName(); + AbstractTypeDefinitionWrapper objectTypeDef = createTypeDef(classQName); + if(objectTypeDef != null) + { + cmisRegistry.registerTypeDefinition(objectTypeDef); + ret.add(objectTypeDef); + } + } + + return ret; + } + }; + } + + /** + * Create Type Definitions + * + * @param classQName QName + */ + private AbstractTypeDefinitionWrapper createTypeDef(QName classQName) + { + AbstractTypeDefinitionWrapper objectTypeDef = null; + + // skip items that are remapped to CMIS model + if(!cmisMapping.isRemappedType(classQName)) + { + // create appropriate kind of type definition + ClassDefinition classDef = dictionaryService.getClass(classQName); + String typeId = null; + if (cmisMapping.isValidCmisDocument(classQName)) + { + typeId = cmisMapping.getCmisTypeId(BaseTypeId.CMIS_DOCUMENT, classQName); + objectTypeDef = new DocumentTypeDefinitionWrapper(cmisMapping, accessorMapping, luceneBuilderMapping, typeId, dictionaryService, classDef); + } + else if (cmisMapping.isValidCmisFolder(classQName)) + { + typeId = cmisMapping.getCmisTypeId(BaseTypeId.CMIS_FOLDER, classQName); + objectTypeDef = new FolderTypeDefintionWrapper(cmisMapping, accessorMapping, luceneBuilderMapping, typeId, dictionaryService, classDef); + } + else if (cmisMapping.getCmisVersion().equals(CmisVersion.CMIS_1_1) && cmisMapping.isValidCmisSecondaryType(classQName)) + { + typeId = cmisMapping.getCmisTypeId(BaseTypeId.CMIS_SECONDARY, classQName); + objectTypeDef = new SecondaryTypeDefinitionWrapper(cmisMapping, accessorMapping, luceneBuilderMapping, typeId, dictionaryService, classDef); + } + else if (cmisMapping.isValidCmisPolicy(classQName)) + { + typeId = cmisMapping.getCmisTypeId(BaseTypeId.CMIS_POLICY, classQName); + objectTypeDef = new PolicyTypeDefintionWrapper(cmisMapping, accessorMapping, luceneBuilderMapping, typeId, dictionaryService, classDef); + } + else if (cmisMapping.isValidCmisItem(classQName)) + { + typeId = cmisMapping.getCmisTypeId(BaseTypeId.CMIS_ITEM, classQName); + objectTypeDef = new ItemTypeDefinitionWrapper(cmisMapping, accessorMapping, luceneBuilderMapping, typeId, dictionaryService, classDef); + } + } + + return objectTypeDef; + } + + private Collection createTypeDefs(CMISDictionaryRegistry registry, + Collection classQNames) + { + Collection ret = new LinkedList<>(); + + for (QName classQName : classQNames) + { + AbstractTypeDefinitionWrapper objectTypeDef = createTypeDef(classQName); + if (objectTypeDef != null) + { + registry.registerTypeDefinition(objectTypeDef); + ret.add(objectTypeDef); + } + } + + return ret; + } + + private RelationshipTypeDefintionWrapper createAssocDef(QName classQName) + { + RelationshipTypeDefintionWrapper assocTypeDef = null; + + if(cmisMapping.isValidCmisRelationship(classQName)) + { + // create appropriate kind of type definition + AssociationDefinition assocDef = dictionaryService.getAssociation(classQName); + String typeId = cmisMapping.getCmisTypeId(BaseTypeId.CMIS_RELATIONSHIP, classQName); + assocTypeDef = new RelationshipTypeDefintionWrapper(cmisMapping, accessorMapping, luceneBuilderMapping, + typeId, dictionaryService, assocDef); + } + + return assocTypeDef; + } + + /** + * Create Relationship Definitions + * + * @param registry CMISDictionaryRegistry + * @param classQNames Collection createAssocDefs(CMISDictionaryRegistry registry, + Collection classQNames) + { + Collection ret = new LinkedList<>(); + + // register all other relationships + for (QName classQName : classQNames) + { + RelationshipTypeDefintionWrapper assocTypeDef = createAssocDef(classQName); + if(assocTypeDef != null) + { + registry.registerTypeDefinition(assocTypeDef); + ret.add(assocTypeDef); + } + } + + return ret; + } + + @Override + protected DictionaryInitializer getCoreDictionaryInitializer() + { + return coreDictionaryInitializer; + } + + @Override + protected DictionaryInitializer getTenantDictionaryInitializer() + { + return tenantDictionaryInitializer; + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/DocumentTypeDefinitionWrapper.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/DocumentTypeDefinitionWrapper.java new file mode 100644 index 0000000000..0b334e3591 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/DocumentTypeDefinitionWrapper.java @@ -0,0 +1,141 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.Collection; + +import org.alfresco.opencmis.CMISUtils; +import org.alfresco.opencmis.mapping.CMISMapping; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ISO9075; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.chemistry.opencmis.commons.enums.ContentStreamAllowed; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.DocumentTypeDefinitionImpl; + +public class DocumentTypeDefinitionWrapper extends ShadowTypeDefinitionWrapper +{ + private static final long serialVersionUID = 1L; + + private DocumentTypeDefinitionImpl typeDef; + private DocumentTypeDefinitionImpl typeDefInclProperties; + private DictionaryService dictionaryService; + + public DocumentTypeDefinitionWrapper(CMISMapping cmisMapping, PropertyAccessorMapping accessorMapping, + PropertyLuceneBuilderMapping luceneBuilderMapping, String typeId, DictionaryService dictionaryService, ClassDefinition cmisClassDef) + { + this.dictionaryService = dictionaryService; + alfrescoName = cmisClassDef.getName(); + alfrescoClass = cmisMapping.getAlfrescoClass(alfrescoName); + + typeDef = new DocumentTypeDefinitionImpl(); + + typeDef.setBaseTypeId(BaseTypeId.CMIS_DOCUMENT); + typeDef.setId(typeId); + typeDef.setLocalName(alfrescoName.getLocalName()); + typeDef.setLocalNamespace(alfrescoName.getNamespaceURI()); + + if (BaseTypeId.CMIS_DOCUMENT.value().equals(typeId)) + { + typeDef.setQueryName(ISO9075.encodeSQL(typeId)); + typeDef.setParentTypeId(null); + } else + { + typeDef.setQueryName(ISO9075.encodeSQL(cmisMapping.buildPrefixEncodedString(alfrescoName))); + QName parentQName = cmisMapping.getCmisType(cmisClassDef.getParentName()); + if (cmisMapping.isValidCmisDocument(parentQName)) + { + typeDef.setParentTypeId(cmisMapping.getCmisTypeId(BaseTypeId.CMIS_DOCUMENT, parentQName)); + } + } + + typeDef.setDisplayName(null); + typeDef.setDescription(null); + + typeDef.setIsCreatable(true); + typeDef.setIsQueryable(true); + typeDef.setIsFulltextIndexed(true); + typeDef.setIsControllablePolicy(false); + typeDef.setIsControllableAcl(true); + typeDef.setIsIncludedInSupertypeQuery(cmisClassDef.getIncludedInSuperTypeQuery()); + typeDef.setIsFileable(true); + typeDef.setContentStreamAllowed(ContentStreamAllowed.ALLOWED); + typeDef.setIsVersionable(true); + + typeDefInclProperties = CMISUtils.copy(typeDef); + setTypeDefinition(typeDef, typeDefInclProperties); + + createOwningPropertyDefinitions(cmisMapping, accessorMapping, luceneBuilderMapping, dictionaryService, cmisClassDef); + createActionEvaluators(accessorMapping, BaseTypeId.CMIS_DOCUMENT); + } + + @Override + public void updateDefinition(DictionaryService dictionaryService) + { + TypeDefinition typeDef = dictionaryService.getType(alfrescoName); + + if (typeDef != null) + { + setTypeDefDisplayName(typeDef.getTitle(dictionaryService)); + setTypeDefDescription(typeDef.getDescription(dictionaryService)); + } + else + { + super.updateDefinition(dictionaryService); + } + + updateTypeDefInclProperties(); + } + + @Override + public PropertyDefinitionWrapper getPropertyById(String propertyId) + { + updateProperty(dictionaryService, propertiesById.get(propertyId)); + return propertiesById.get(propertyId); + } + + @Override + public Collection getProperties() + { + updateProperties(dictionaryService); + return propertiesById.values(); + } + + @Override + public Collection getProperties(boolean update) + { + if (update) + { + return getProperties(); + } + else + { + return propertiesById.values(); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/FilteredDictionaryComponent.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/FilteredDictionaryComponent.java new file mode 100644 index 0000000000..42240855e2 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/FilteredDictionaryComponent.java @@ -0,0 +1,93 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.Collection; + +import org.alfresco.repo.dictionary.DictionaryComponent; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.QName; + +/** + * A DictionaryComponent that uses a QNameFilter to constrain what is returned. + * + * @author Gethin James + */ +public class FilteredDictionaryComponent extends DictionaryComponent +{ + QNameFilter filter; + + @Override + public Collection getAllTypes() + { + return filter.filterQName(super.getAllTypes()); + } + + @Override + public Collection getSubTypes(QName superType, boolean follow) + { + return filter.filterQName(super.getSubTypes(superType, follow)); + } + + @Override + public Collection getAllAspects() + { + return filter.filterQName(super.getAllAspects()); + } + + @Override + public Collection getAllAssociations() + { + return filter.filterQName(super.getAllAssociations()); + } + + @Override + public Collection getSubAspects(QName superAspect, boolean follow) + { + return filter.filterQName(super.getSubAspects(superAspect, follow)); + } + + @Override + public TypeDefinition getType(QName name) + { + if (filter.isExcluded(name)) return null; //Don't return an excluded type + return super.getType(name); + } + + @Override + public AspectDefinition getAspect(QName name) + { + if (filter.isExcluded(name)) return null; //Don't return an excluded type + return super.getAspect(name); + } + + public void setFilter(QNameFilter filter) + { + this.filter = filter; + } + +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/FolderTypeDefintionWrapper.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/FolderTypeDefintionWrapper.java new file mode 100644 index 0000000000..4b3dc9e6e6 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/FolderTypeDefintionWrapper.java @@ -0,0 +1,147 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.Collection; + +import org.alfresco.model.ContentModel; +import org.alfresco.opencmis.CMISUtils; +import org.alfresco.opencmis.mapping.CMISMapping; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ISO9075; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.FolderTypeDefinitionImpl; + +public class FolderTypeDefintionWrapper extends ShadowTypeDefinitionWrapper +{ + private static final long serialVersionUID = 1L; + + private FolderTypeDefinitionImpl typeDef; + private FolderTypeDefinitionImpl typeDefInclProperties; + private DictionaryService dictionaryService; + + + public FolderTypeDefintionWrapper(CMISMapping cmisMapping, PropertyAccessorMapping accessorMapping, + PropertyLuceneBuilderMapping luceneBuilderMapping, String typeId, DictionaryService dictionaryService, ClassDefinition cmisClassDef) + { + this.dictionaryService = dictionaryService; + alfrescoName = cmisClassDef.getName(); + alfrescoClass = cmisMapping.getAlfrescoClass(alfrescoName); + + typeDef = new FolderTypeDefinitionImpl(); + + typeDef.setBaseTypeId(BaseTypeId.CMIS_FOLDER); + typeDef.setId(typeId); + typeDef.setLocalName(alfrescoName.getLocalName()); + typeDef.setLocalNamespace(alfrescoName.getNamespaceURI()); + + boolean isSystemFolder = false; + if (BaseTypeId.CMIS_FOLDER.value().equals(typeId)) + { + typeDef.setQueryName(ISO9075.encodeSQL(typeId)); + typeDef.setParentTypeId(null); + } else + { + typeDef.setQueryName(ISO9075.encodeSQL(cmisMapping.buildPrefixEncodedString(alfrescoName))); + QName parentQName = cmisMapping.getCmisType(cmisClassDef.getParentName()); + if (cmisMapping.isValidCmisFolder(parentQName)) + { + typeDef.setParentTypeId(cmisMapping.getCmisTypeId(BaseTypeId.CMIS_FOLDER, parentQName)); + } + + if (alfrescoName.equals(ContentModel.TYPE_SYSTEM_FOLDER) + || cmisMapping.getDictionaryService().isSubClass(alfrescoName, ContentModel.TYPE_SYSTEM_FOLDER)) + { + isSystemFolder = true; + } + } + + typeDef.setDisplayName(null); + typeDef.setDescription(null); + + typeDef.setIsCreatable(!isSystemFolder); + typeDef.setIsQueryable(true); + typeDef.setIsFulltextIndexed(true); + typeDef.setIsControllablePolicy(false); + typeDef.setIsControllableAcl(true); + typeDef.setIsIncludedInSupertypeQuery(cmisClassDef.getIncludedInSuperTypeQuery()); + typeDef.setIsFileable(true); + + typeDefInclProperties = CMISUtils.copy(typeDef); + setTypeDefinition(typeDef, typeDefInclProperties); + + createOwningPropertyDefinitions(cmisMapping, accessorMapping, luceneBuilderMapping, dictionaryService, cmisClassDef); + createActionEvaluators(accessorMapping, BaseTypeId.CMIS_FOLDER); + } + + @Override + public void updateDefinition(DictionaryService dictionaryService) + { + TypeDefinition typeDef = dictionaryService.getType(alfrescoName); + + if (typeDef != null) + { + setTypeDefDisplayName(typeDef.getTitle(dictionaryService)); + setTypeDefDescription(typeDef.getDescription(dictionaryService)); + } + else + { + super.updateDefinition(dictionaryService); + } + + updateTypeDefInclProperties(); + } + + @Override + public PropertyDefinitionWrapper getPropertyById(String propertyId) + { + updateProperty(dictionaryService, propertiesById.get(propertyId)); + return propertiesById.get(propertyId); + } + + @Override + public Collection getProperties() + { + updateProperties(dictionaryService); + return propertiesById.values(); + } + + @Override + public Collection getProperties(boolean update) + { + if (update) + { + return getProperties(); + } + else + { + return propertiesById.values(); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/ItemTypeDefinitionWrapper.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/ItemTypeDefinitionWrapper.java new file mode 100644 index 0000000000..ffa77fca81 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/ItemTypeDefinitionWrapper.java @@ -0,0 +1,149 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.Collection; + +import org.alfresco.opencmis.CMISUtils; +import org.alfresco.opencmis.mapping.CMISMapping; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ISO9075; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.ItemTypeDefinitionImpl; + +public class ItemTypeDefinitionWrapper extends ShadowTypeDefinitionWrapper +{ + private static final long serialVersionUID = 1L; + + private ItemTypeDefinitionImpl typeDef; + private ItemTypeDefinitionImpl typeDefInclProperties; + private DictionaryService dictionaryService; + + public ItemTypeDefinitionWrapper(CMISMapping cmisMapping, PropertyAccessorMapping accessorMapping, + PropertyLuceneBuilderMapping luceneBuilderMapping, String typeId, DictionaryService dictionaryService, ClassDefinition cmisClassDef) + { + this.dictionaryService = dictionaryService; + alfrescoName = cmisClassDef.getName(); + alfrescoClass = cmisMapping.getAlfrescoClass(alfrescoName); + + typeDef = new ItemTypeDefinitionImpl(); + + typeDef.setBaseTypeId(BaseTypeId.CMIS_ITEM); + typeDef.setId(typeId); + typeDef.setLocalName(alfrescoName.getLocalName()); + typeDef.setLocalNamespace(alfrescoName.getNamespaceURI()); + + if (BaseTypeId.CMIS_ITEM.value().equals(typeId) ) + { + typeDef.setQueryName(ISO9075.encodeSQL(typeId)); + typeDef.setParentTypeId(null); + } + else + { + typeDef.setQueryName(ISO9075.encodeSQL(cmisMapping.buildPrefixEncodedString(alfrescoName))); + QName parentQName = cmisMapping.getCmisType(cmisClassDef.getParentName()); + if(parentQName != null) + { + typeDef.setParentTypeId(cmisMapping.getCmisTypeId(BaseTypeId.CMIS_ITEM, parentQName)); + } + } + + typeDef.setDisplayName(null); + typeDef.setDescription(null); + + if (BaseTypeId.CMIS_ITEM.value().equals(typeId) ) + { + typeDef.setIsCreatable(false); // cmis:item is abstract + // TEMP work around for select * from cmis:item which lists folders and files + typeDef.setIsQueryable(false); + } + else + { + typeDef.setIsCreatable(true); + typeDef.setIsQueryable(true); + } + + typeDef.setIsFulltextIndexed(true); + typeDef.setIsControllablePolicy(true); + typeDef.setIsControllableAcl(true); + typeDef.setIsIncludedInSupertypeQuery(cmisClassDef.getIncludedInSuperTypeQuery()); + typeDef.setIsFileable(false); + + typeDefInclProperties = CMISUtils.copy(typeDef); + setTypeDefinition(typeDef, typeDefInclProperties); + + createOwningPropertyDefinitions(cmisMapping, accessorMapping, luceneBuilderMapping, dictionaryService, cmisClassDef); + createActionEvaluators(accessorMapping, BaseTypeId.CMIS_ITEM); + } + + @Override + public void updateDefinition(DictionaryService dictionaryService) + { + TypeDefinition typeDef = dictionaryService.getType(alfrescoName); + + if (typeDef != null) + { + setTypeDefDisplayName(typeDef.getTitle(dictionaryService)); + setTypeDefDescription(typeDef.getDescription(dictionaryService)); + } + else + { + super.updateDefinition(dictionaryService); + } + + updateTypeDefInclProperties(); + } + + @Override + public PropertyDefinitionWrapper getPropertyById(String propertyId) + { + updateProperty(dictionaryService, propertiesById.get(propertyId)); + return propertiesById.get(propertyId); + } + + @Override + public Collection getProperties() + { + updateProperties(dictionaryService); + return propertiesById.values(); + } + + @Override + public Collection getProperties(boolean update) + { + if (update) + { + return getProperties(); + } + else + { + return propertiesById.values(); + } + } +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/PolicyTypeDefintionWrapper.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/PolicyTypeDefintionWrapper.java new file mode 100644 index 0000000000..a524302f25 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/PolicyTypeDefintionWrapper.java @@ -0,0 +1,277 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.opencmis.CMISUtils; +import org.alfresco.opencmis.mapping.CMISMapping; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ISO9075; +import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.PolicyTypeDefinitionImpl; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class PolicyTypeDefintionWrapper extends AbstractTypeDefinitionWrapper +{ + private static final long serialVersionUID = 1L; + // Logger + protected static final Log logger = LogFactory.getLog(PolicyTypeDefintionWrapper.class); + + private PolicyTypeDefinitionImpl typeDef; + private PolicyTypeDefinitionImpl typeDefInclProperties; + private DictionaryService dictionaryService; + + public PolicyTypeDefintionWrapper(CMISMapping cmisMapping, PropertyAccessorMapping propertyAccessorMapping, + PropertyLuceneBuilderMapping luceneBuilderMapping, String typeId, DictionaryService dictionaryService, ClassDefinition cmisClassDef) + { + this.dictionaryService = dictionaryService; + alfrescoName = cmisClassDef.getName(); + alfrescoClass = cmisMapping.getAlfrescoClass(alfrescoName); + + typeDef = new PolicyTypeDefinitionImpl(); + + typeDef.setBaseTypeId(BaseTypeId.CMIS_POLICY); + typeDef.setId(typeId); + typeDef.setLocalName(alfrescoName.getLocalName()); + typeDef.setLocalNamespace(alfrescoName.getNamespaceURI()); + + if (BaseTypeId.CMIS_POLICY.value().equals(typeId)) + { + typeDef.setQueryName(ISO9075.encodeSQL(typeId)); + typeDef.setParentTypeId(null); + } else + { + typeDef.setQueryName(ISO9075.encodeSQL(cmisMapping.buildPrefixEncodedString(alfrescoName))); + QName parentQName = cmisMapping.getCmisType(cmisClassDef.getParentName()); + if (parentQName == null) + { + typeDef.setParentTypeId(cmisMapping.getCmisTypeId(CMISMapping.ASPECTS_QNAME)); + } else if (cmisMapping.isValidCmisPolicy(parentQName)) + { + typeDef.setParentTypeId(cmisMapping.getCmisTypeId(BaseTypeId.CMIS_POLICY, parentQName)); + } else + { + throw new IllegalStateException("The CMIS type model should ignore aspects that inherit from excluded aspects"); + } + } + + typeDef.setDisplayName(null); + typeDef.setDescription(null); + + typeDef.setIsCreatable(false); + typeDef.setIsQueryable(true); + typeDef.setIsFulltextIndexed(true); + typeDef.setIsControllablePolicy(false); + typeDef.setIsControllableAcl(false); + typeDef.setIsIncludedInSupertypeQuery(cmisClassDef.getIncludedInSuperTypeQuery()); + typeDef.setIsFileable(false); + + typeDefInclProperties = CMISUtils.copy(typeDef); + setTypeDefinition(typeDef, typeDefInclProperties); + + createOwningPropertyDefinitions(cmisMapping, propertyAccessorMapping, luceneBuilderMapping, dictionaryService, cmisClassDef); + createActionEvaluators(propertyAccessorMapping, BaseTypeId.CMIS_POLICY); + } + + @Override + public List connectParentAndSubTypes(CMISMapping cmisMapping, CMISDictionaryRegistry registry, + DictionaryService dictionaryService) + { + String parentTypeId = typeDef.getParentTypeId(); + + // find parent + if (typeDef.getParentTypeId() != null) + { + parent = registry.getTypeDefByTypeId(parentTypeId); +// if(registry.getTenant() != null && parent != null && registry.getTypeDefByTypeId(parentTypeId, false) == null) +// { +// // this is a tenant registry and the parent is not defined locally so add this type as a child of it +// registry.addChild(parent.getTypeId(), this); +// } + } + else + { + if (!isBaseType()) + { + throw new AlfrescoRuntimeException("Type " + typeDef.getId() + " has no parent!"); + } + + parent = null; + } + + // find children + Collection childrenNames = null; + + if (isBaseType()) + { + // add the "Aspects" type to the CMIS Policy type + childrenNames = new ArrayList(); + childrenNames.add(CMISMapping.ASPECTS_QNAME); + } + else if (getAlfrescoName().equals(CMISMapping.ASPECTS_QNAME)) + { + // add all root aspects to the "Aspects" type + childrenNames = new ArrayList(); + + String aspectsTypeId = cmisMapping.getCmisTypeId(CMISMapping.ASPECTS_QNAME); + for (AbstractTypeDefinitionWrapper tdw : registry.getTypeDefs(false)) + { +// TypeDefinitionWrapper parent = tdw.getParent(); +// if(tdw.getTenantId().equals(parent.getTenantId())) +// { + // type and parent in same tenant +// } + String parentId = tdw.getTypeDefinition(false).getParentTypeId(); + if ((parentId != null) && parentId.equals(aspectsTypeId)) + { + childrenNames.add(tdw.getAlfrescoName()); + } + } + } + else + { + // add all non-root aspects in this tenant to their parent + childrenNames = dictionaryService.getSubAspects(cmisMapping.getAlfrescoClass(getAlfrescoName()), false); + } + + List children = new LinkedList(); + for (QName childName : childrenNames) + { + if (cmisMapping.isValidCmisPolicy(childName)) + { + TypeDefinitionWrapper child = registry.getTypeDefByQName(childName); + + if (child == null) + { + throw new AlfrescoRuntimeException("Failed to retrieve sub type for type id " + childName + + " for parent type " + getAlfrescoName() + "!"); + } + children.add(child); + } + else + { + logger.info("Not a policy: " + childName); + } + } + + return children; +// registry.setChildren(typeDef.getId(), children); + } + + public void resolveInheritance(CMISMapping cmisMapping, + CMISDictionaryRegistry registry, DictionaryService dictionaryService) + { + PropertyDefinition propertyDefintion; + + if (parent != null) + { + for (PropertyDefinitionWrapper propDef : parent.getProperties(false)) + { + if (propertiesById.containsKey(propDef.getPropertyId())) + { + continue; + } + + org.alfresco.service.cmr.dictionary.PropertyDefinition alfrescoPropDef = dictionaryService.getProperty( + propDef.getOwningType().getAlfrescoName(), propDef.getAlfrescoName()); + + propertyDefintion = createPropertyDefinition(cmisMapping, propDef.getPropertyId(), + alfrescoPropDef.getName(), dictionaryService, alfrescoPropDef, true); + + if (propertyDefintion != null) + { + registerProperty(new BasePropertyDefintionWrapper(propertyDefintion, alfrescoPropDef.getName(), + propDef.getOwningType(), propDef.getPropertyAccessor(), propDef.getPropertyLuceneBuilder())); + } + } + } + + List children = registry.getChildren(typeDef.getId()); + for (TypeDefinitionWrapper child : children) + { + if (child instanceof AbstractTypeDefinitionWrapper) + { + ((AbstractTypeDefinitionWrapper) child).resolveInheritance(cmisMapping, registry, + dictionaryService); + } + } + } + + @Override + public void updateDefinition(DictionaryService dictionaryService) + { + AspectDefinition aspectDef = dictionaryService.getAspect(alfrescoName); + + if (aspectDef != null) + { + setTypeDefDisplayName(aspectDef.getTitle(dictionaryService)); + setTypeDefDescription(aspectDef.getDescription(dictionaryService)); + } + else + { + super.updateDefinition(dictionaryService); + } + + updateTypeDefInclProperties(); + } + + @Override + public PropertyDefinitionWrapper getPropertyById(String propertyId) + { + updateProperty(dictionaryService, propertiesById.get(propertyId)); + return propertiesById.get(propertyId); + } + + @Override + public Collection getProperties() + { + updateProperties(dictionaryService); + return propertiesById.values(); + } + + @Override + public Collection getProperties(boolean update) + { + if (update) + { + return getProperties(); + } + else + { + return propertiesById.values(); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/PropertyAccessorMapping.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/PropertyAccessorMapping.java new file mode 100644 index 0000000000..2b44d698f3 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/PropertyAccessorMapping.java @@ -0,0 +1,65 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.Map; + +import org.alfresco.service.namespace.QName; +import org.apache.chemistry.opencmis.commons.enums.Action; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; + + +/** + * Encapsulate the mapping of property to property accessor + * + * @author davidc + */ +public interface PropertyAccessorMapping +{ + /** + * Gets a property accessor + * + * @param propertyId property id + * @return property accessor + */ + public CMISPropertyAccessor getPropertyAccessor(String propertyId); + + /** + * Create a direct node property accessor + * + * @param propertyId property id + * @param propertyName node property name + * @return property accessor + */ + public CMISPropertyAccessor createDirectPropertyAccessor(String propertyId, QName propertyName); + + /** + * Gets the Action Evaluators applicable for the given CMIS Scope + * + * @param scope BaseTypeId + */ + public Map getActionEvaluators(BaseTypeId scope); +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/PropertyDefinitionWrapper.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/PropertyDefinitionWrapper.java new file mode 100644 index 0000000000..898dfaafdf --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/PropertyDefinitionWrapper.java @@ -0,0 +1,44 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import org.alfresco.service.namespace.QName; +import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition; + +public interface PropertyDefinitionWrapper +{ + PropertyDefinition getPropertyDefinition(); + + String getPropertyId(); + + QName getAlfrescoName(); + + TypeDefinitionWrapper getOwningType(); + + CMISPropertyAccessor getPropertyAccessor(); + + CMISPropertyLuceneBuilder getPropertyLuceneBuilder(); +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/PropertyLuceneBuilderMapping.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/PropertyLuceneBuilderMapping.java new file mode 100644 index 0000000000..44307c106c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/PropertyLuceneBuilderMapping.java @@ -0,0 +1,52 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import org.alfresco.service.namespace.QName; + +/** + * Encapsulate the mapping of property to lucene builder + * + * @author davidc + */ +public interface PropertyLuceneBuilderMapping +{ + /** + * Gets a property lucene builder + * + * @param propertyId property id + * @return property builder + */ + public CMISPropertyLuceneBuilder getPropertyLuceneBuilder(String propertyId); + + /** + * Create a direct node property lucene builder + * + * @param propertyName node property name + * @return property lucene builder + */ + public CMISPropertyLuceneBuilder createDirectPropertyLuceneBuilder(QName propertyName); +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/QNameFilter.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/QNameFilter.java new file mode 100644 index 0000000000..380a12ecff --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/QNameFilter.java @@ -0,0 +1,67 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.Collection; + +import org.alfresco.service.namespace.QName; + +/** + * Filters QNames and excludes any + * that are in a predefined list. + * + * @author steveglover + * @author Gethin James + */ +public interface QNameFilter +{ + public static final String WILDCARD = "*"; + + /** + * Filters out any QName defined in the "excludedTypes" property + * + * @param typesToFilter - original list + * @return the filtered list + */ + Collection filterQName(Collection typesToFilter); + + /** + * Indicates that this QName should be excluded. + * @param typeQName QName + * @return boolean true if it is excluded + */ + boolean isExcluded(QName typeQName); + + /** + * Exclude the type + * + * @param typeQName the type to exclude + * + */ + void setExcluded(QName typeQName, boolean excluded); + + void initFilter(); +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/QNameFilterImpl.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/QNameFilterImpl.java new file mode 100644 index 0000000000..965f7f9a67 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/QNameFilterImpl.java @@ -0,0 +1,192 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.service.namespace.QName; + +/** + * Filters a QName and excludes any + * that are defined using the excludedTypes parameter. + * The list of types can either be defined using a property name such as "cm:name" or with a wildcard: "cm:*" + * It validates the definitions against the DataDictionary. + * + * @author steveglover + * @author Gethin James + */ +public class QNameFilterImpl implements QNameFilter +{ + private Map excludedQNames; + private Set excludedModels; + + private List excludedTypes; + + /** + * Filters out any QName defined in the "excludedModels" property + * + * @param typesToFilter - original list + * @return the filtered list + */ + public Collection filterQName(Collection typesToFilter) + { + Collection filteredTypes = new ArrayList(); + if (!excludedQNames.isEmpty() || !excludedModels.isEmpty()) + { + //If we have a exclusion list then loop through and exclude models /types + //that are in this list. + for (QName classQName : typesToFilter) + { + if(!isExcluded(classQName)) +// if (!excludedQNames.contains(classQName) && !excludedModels.contains(classQName.getNamespaceURI())) + { + //Not excluded so add it + filteredTypes.add(classQName); + } + } + } + else + { + filteredTypes = typesToFilter; + } + return filteredTypes; + } + + + /** + * Processes the user-defined list of types into valid QNames and models, it validates them + * against the dictionary and also supports wildcards + */ + protected void preprocessExcludedTypes(List excludeTypeNames) + { + if (excludeTypeNames == null || excludeTypeNames.isEmpty()) return; + + Map qNamesToExclude = new HashMap(); + Set modelsToExclude = new HashSet(); + + for (String typeDefinition : excludeTypeNames) + { + final QName typeDef = QName.createQName(typeDefinition); + if (WILDCARD.equals(typeDef.getLocalName())) + { + modelsToExclude.add(typeDef.getNamespaceURI()); + } + else + { + qNamesToExclude.put(typeDef, Boolean.TRUE); // valid so add it to the list + } + } + + this.excludedModels = modelsToExclude; + this.excludedQNames = qNamesToExclude; + } + + /** + * Indicates that this QName should be excluded. + * @param typeQName QName + * @return boolean true if it is excluded + */ + public boolean isExcluded(QName typeQName) + { + Boolean isExcluded = excludedQNames.get(typeQName); + return (isExcluded != null && isExcluded.booleanValue() || excludedModels.contains(typeQName.getNamespaceURI())); + } + + @Override + public void initFilter() + { + if (excludedTypes == null || excludedTypes.isEmpty()) + { + excludedTypes = listOfHardCodedExcludedTypes(); + } + preprocessExcludedTypes(excludedTypes); + } + + public void setExcludedTypes(List excludedTypes) + { + this.excludedTypes = excludedTypes; + } + + /** + * I don't like hard code values, but have been persuaded its less pain + * than having to keep a config file in sync with both sides of SOLR. + * + */ + public static List listOfHardCodedExcludedTypes() { + List hardCodeListOfTypes = new ArrayList(); + + hardCodeListOfTypes.add("{http://www.alfresco.org/model/imap/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishing/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishingworkflow/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishing/twitter/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishing/slideshare/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishing/facebook/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishing/youtube/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishing/linkedin/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/publishing/flickr/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/transfer/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/emailserver/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/calendar}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/blogintegration/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/linksmodel/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/datalist/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/forum/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/cloud/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/bpm/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/workflow/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/workflow/invite/moderated/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/workflow/invite/nominated/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/workflow/cloud/resetpassword/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/workflow/cloud/siteinvitation/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/workflow/signup/selfsignup/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/versionstore/2.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/versionstore/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/action/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/application/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/rule/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/rendition/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/qshare/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/sync/1.0}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/content/1.0}thumbnailed"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/content/1.0}failedThumbnailSource"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/cmis/custom}*"); + hardCodeListOfTypes.add("{http://www.alfresco.org/model/hybridworkflow/1.0}*"); + return hardCodeListOfTypes; + } + + @Override + public void setExcluded(QName typeQName, boolean excluded) + { + excludedQNames.put(typeQName, Boolean.valueOf(excluded)); + } + +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/RelationshipTypeDefintionWrapper.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/RelationshipTypeDefintionWrapper.java new file mode 100644 index 0000000000..affd9ff925 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/RelationshipTypeDefintionWrapper.java @@ -0,0 +1,272 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.opencmis.CMISUtils; +import org.alfresco.opencmis.mapping.CMISMapping; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.util.ISO9075; +import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.RelationshipTypeDefinitionImpl; + +public class RelationshipTypeDefintionWrapper extends AbstractTypeDefinitionWrapper +{ + private static final long serialVersionUID = 1L; + + private RelationshipTypeDefinitionImpl typeDef; + private RelationshipTypeDefinitionImpl typeDefInclProperties; + private DictionaryService dictionaryService; + + public RelationshipTypeDefintionWrapper(CMISMapping cmisMapping, PropertyAccessorMapping accessorMapping, + PropertyLuceneBuilderMapping luceneBuilderMapping, String typeId, DictionaryService dictionaryService, ClassDefinition cmisClassDef) + { + this.dictionaryService = dictionaryService; + alfrescoName = cmisClassDef.getName(); + alfrescoClass = cmisMapping.getAlfrescoClass(alfrescoName); + + typeDef = new RelationshipTypeDefinitionImpl(); + + typeDef.setBaseTypeId(BaseTypeId.CMIS_RELATIONSHIP); + typeDef.setId(typeId); + typeDef.setLocalName(alfrescoName.getLocalName()); + typeDef.setLocalNamespace(alfrescoName.getNamespaceURI()); + + if (BaseTypeId.CMIS_RELATIONSHIP.value().equals(typeId)) + { + typeDef.setQueryName(ISO9075.encodeSQL(typeId)); + typeDef.setParentTypeId(null); + typeDef.setIsCreatable(false); + } else + { + typeDef.setQueryName(ISO9075.encodeSQL(cmisMapping.buildPrefixEncodedString(alfrescoName))); + typeDef.setParentTypeId(BaseTypeId.CMIS_RELATIONSHIP.value()); + typeDef.setIsCreatable(true); + } + + typeDef.setDisplayName(null); + typeDef.setDescription(null); + + typeDef.setIsQueryable(false); + typeDef.setIsFulltextIndexed(false); + typeDef.setIsControllablePolicy(false); + typeDef.setIsControllableAcl(false); + typeDef.setIsIncludedInSupertypeQuery(true); + typeDef.setIsFileable(false); + + typeDefInclProperties = CMISUtils.copy(typeDef); + setTypeDefinition(typeDef, typeDefInclProperties); + + createOwningPropertyDefinitions(cmisMapping, accessorMapping, luceneBuilderMapping, dictionaryService, cmisClassDef); + createActionEvaluators(accessorMapping, BaseTypeId.CMIS_RELATIONSHIP); + } + + public RelationshipTypeDefintionWrapper(CMISMapping cmisMapping, PropertyAccessorMapping accessorMapping, + PropertyLuceneBuilderMapping luceneBuilderMapping, String typeId, DictionaryService dictionaryService, AssociationDefinition cmisAssocDef) + { + this.dictionaryService = dictionaryService; + alfrescoName = cmisAssocDef.getName(); + alfrescoClass = cmisMapping.getAlfrescoClass(alfrescoName); + + typeDef = new RelationshipTypeDefinitionImpl(); + + typeDef.setBaseTypeId(BaseTypeId.CMIS_RELATIONSHIP); + typeDef.setId(typeId); + typeDef.setLocalName(alfrescoName.getLocalName()); + typeDef.setLocalNamespace(alfrescoName.getNamespaceURI()); + + typeDef.setQueryName(cmisMapping.buildPrefixEncodedString(alfrescoName)); + typeDef.setParentTypeId(BaseTypeId.CMIS_RELATIONSHIP.value()); + + typeDef.setDisplayName(null); + typeDef.setDescription(null); + + typeDef.setIsCreatable(true); + typeDef.setIsQueryable(false); + typeDef.setIsFulltextIndexed(false); + typeDef.setIsControllablePolicy(false); + typeDef.setIsControllableAcl(false); + typeDef.setIsIncludedInSupertypeQuery(true); + typeDef.setIsFileable(false); + + ArrayList both = new ArrayList(2); + both.add(BaseTypeId.CMIS_DOCUMENT.value()); + both.add(BaseTypeId.CMIS_FOLDER.value()); + + String sourceTypeId = cmisMapping.getCmisTypeId(cmisMapping + .getCmisType(cmisAssocDef.getSourceClass().getName())); + if (sourceTypeId != null) + { + typeDef.setAllowedSourceTypes(Collections.singletonList(sourceTypeId)); + } + else + { + typeDef.setAllowedSourceTypes(both); + } + + String targetTypeId = cmisMapping.getCmisTypeId(cmisMapping + .getCmisType(cmisAssocDef.getTargetClass().getName())); + if (targetTypeId != null) + { + typeDef.setAllowedTargetTypes(Collections.singletonList(targetTypeId)); + } + else + { + typeDef.setAllowedTargetTypes(both); + } + + typeDefInclProperties = CMISUtils.copy(typeDef); + setTypeDefinition(typeDef, typeDefInclProperties); + createActionEvaluators(accessorMapping, BaseTypeId.CMIS_RELATIONSHIP); + } + + @Override + public List connectParentAndSubTypes(CMISMapping cmisMapping, CMISDictionaryRegistry registry, + DictionaryService dictionaryService) + { + String parentTypeId = typeDef.getParentTypeId(); + + // find parent + if (parentTypeId != null) + { + parent = registry.getTypeDefByTypeId(parentTypeId); + if(registry.getTenant() != null && parent != null && registry.getTypeDefByTypeId(parentTypeId, false) == null) + { + // this is a tenant registry and the parent is not defined locally so add this type as a child of it + registry.addChild(parent.getTypeId(), this); + } + } + else + { + if (!isBaseType()) + { + throw new AlfrescoRuntimeException("Type " + typeDef.getId() + " has no parent!"); + } + + parent = null; + } + + // find children + List children = new LinkedList(); + if (isBaseType()) + { + for (TypeDefinitionWrapper child : registry.getAssocDefs()) + { + children.add(child); + } + } + + return children; +// registry.setChildren(typeDef.getId(), children); + } + + public void resolveInheritance(CMISMapping cmisMapping, CMISDictionaryRegistry registry, + DictionaryService dictionaryService) + { + PropertyDefinition propertyDefintion; + + if (parent != null) + { + for (PropertyDefinitionWrapper propDef : parent.getProperties(false)) + { + org.alfresco.service.cmr.dictionary.PropertyDefinition alfrescoPropDef = dictionaryService.getProperty( + propDef.getOwningType().getAlfrescoName(), propDef.getAlfrescoName()); + + propertyDefintion = createPropertyDefinition(cmisMapping, propDef.getPropertyId(), + alfrescoPropDef.getName(), dictionaryService, alfrescoPropDef, true); + + if (propertyDefintion != null) + { + registerProperty(new BasePropertyDefintionWrapper(propertyDefintion, alfrescoPropDef.getName(), + propDef.getOwningType(), propDef.getPropertyAccessor(), propDef.getPropertyLuceneBuilder())); + } + } + } + + List children = registry.getChildren(typeDef.getId()); + for (TypeDefinitionWrapper child : children) + { + if (child instanceof AbstractTypeDefinitionWrapper) + { + ((AbstractTypeDefinitionWrapper) child).resolveInheritance(cmisMapping, registry, dictionaryService); + } + } + } + + @Override + public void updateDefinition(DictionaryService dictionaryService) + { + AssociationDefinition assocDef = dictionaryService.getAssociation(alfrescoName); + + if (assocDef != null) + { + setTypeDefDisplayName(assocDef.getTitle(dictionaryService)); + setTypeDefDescription(assocDef.getDescription(dictionaryService)); + } + else + { + super.updateDefinition(dictionaryService); + } + + updateTypeDefInclProperties(); + } + + @Override + public PropertyDefinitionWrapper getPropertyById(String propertyId) + { + updateProperty(dictionaryService, propertiesById.get(propertyId)); + return propertiesById.get(propertyId); + } + + @Override + public Collection getProperties() + { + updateProperties(dictionaryService); + return propertiesById.values(); + } + + @Override + public Collection getProperties(boolean update) + { + if (update) + { + return getProperties(); + } + else + { + return propertiesById.values(); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/SecondaryTypeDefinitionWrapper.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/SecondaryTypeDefinitionWrapper.java new file mode 100644 index 0000000000..8213d9a06f --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/SecondaryTypeDefinitionWrapper.java @@ -0,0 +1,272 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.opencmis.CMISUtils; +import org.alfresco.opencmis.mapping.CMISMapping; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ISO9075; +import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.chemistry.opencmis.commons.impl.dataobjects.SecondaryTypeDefinitionImpl; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class SecondaryTypeDefinitionWrapper extends AbstractTypeDefinitionWrapper +{ + private static final long serialVersionUID = 1L; + // Logger + protected static final Log logger = LogFactory.getLog(SecondaryTypeDefinitionWrapper.class); + + private SecondaryTypeDefinitionImpl typeDef; + private SecondaryTypeDefinitionImpl typeDefInclProperties; + private DictionaryService dictionaryService; + + public SecondaryTypeDefinitionWrapper(CMISMapping cmisMapping, PropertyAccessorMapping propertyAccessorMapping, + PropertyLuceneBuilderMapping luceneBuilderMapping, String typeId, DictionaryService dictionaryService, ClassDefinition cmisClassDef) + { + this.dictionaryService = dictionaryService; + alfrescoName = cmisClassDef.getName(); + alfrescoClass = cmisMapping.getAlfrescoClass(alfrescoName); + + typeDef = new SecondaryTypeDefinitionImpl(); + + typeDef.setBaseTypeId(BaseTypeId.CMIS_SECONDARY); + typeDef.setId(typeId); + typeDef.setLocalName(alfrescoName.getLocalName()); + typeDef.setLocalNamespace(alfrescoName.getNamespaceURI()); + + if (BaseTypeId.CMIS_SECONDARY.value().equals(typeId)) + { + typeDef.setQueryName(ISO9075.encodeSQL(typeId)); + typeDef.setParentTypeId(null); + } + else + { + typeDef.setQueryName(ISO9075.encodeSQL(cmisMapping.buildPrefixEncodedString(alfrescoName))); + QName parentQName = cmisMapping.getCmisType(cmisClassDef.getParentName()); + if (parentQName == null) + { + typeDef.setParentTypeId(cmisMapping.getCmisTypeId(CMISMapping.SECONDARY_TYPES_QNAME)); + } else if (cmisMapping.isValidCmisSecondaryType(parentQName)) + { + typeDef.setParentTypeId(cmisMapping.getCmisTypeId(BaseTypeId.CMIS_SECONDARY, parentQName)); + } else + { + throw new IllegalStateException("The CMIS type model should ignore aspects that inherit from excluded aspects"); + } + } + + typeDef.setDisplayName(null); + typeDef.setDescription(null); + + typeDef.setIsCreatable(false); + typeDef.setIsQueryable(true); + typeDef.setIsFulltextIndexed(true); + typeDef.setIsControllablePolicy(false); + typeDef.setIsControllableAcl(false); + typeDef.setIsIncludedInSupertypeQuery(cmisClassDef.getIncludedInSuperTypeQuery()); + typeDef.setIsFileable(false); + + typeDefInclProperties = CMISUtils.copy(typeDef); + setTypeDefinition(typeDef, typeDefInclProperties); + + createOwningPropertyDefinitions(cmisMapping, propertyAccessorMapping, luceneBuilderMapping, dictionaryService, cmisClassDef); + createActionEvaluators(propertyAccessorMapping, BaseTypeId.CMIS_SECONDARY); + } + + @Override + public List connectParentAndSubTypes(CMISMapping cmisMapping, CMISDictionaryRegistry registry, + DictionaryService dictionaryService) + { + String parentTypeId = typeDef.getParentTypeId(); + + // find parent + if (parentTypeId != null) + { + parent = registry.getTypeDefByTypeId(parentTypeId); + if(registry.getTenant() != null && parent != null && registry.getTypeDefByTypeId(parentTypeId, false) == null) + { + // this is a tenant registry and the parent is not defined locally so add this type as a child of it + registry.addChild(parent.getTypeId(), this); + } + } + else + { + if (!isBaseType()) + { + throw new AlfrescoRuntimeException("Type " + typeDef.getId() + " has no parent!"); + } + + parent = null; + } + + // find children +// children = new ArrayList(); + Collection childrenNames = null; + + if (isBaseType()) + { +// // add the "Aspects" type to the CMIS secondary type +// childrenNames = new ArrayList(); +// childrenNames.add(CMISMapping.SECONDARY_TYPES_QNAME); +// } else if (getAlfrescoName().equals(CMISMapping.SECONDARY_TYPES_QNAME)) +// { + // add all root aspects to the "Aspects" type + childrenNames = new ArrayList(); + + String aspectsTypeId = cmisMapping.getCmisTypeId(CMISMapping.SECONDARY_TYPES_QNAME); + for (AbstractTypeDefinitionWrapper tdw : registry.getTypeDefs()) + { + String parentId = tdw.getTypeDefinition(false).getParentTypeId(); + if ((parentId != null) && parentId.equals(aspectsTypeId)) + { + childrenNames.add(tdw.getAlfrescoName()); + } + } + } else + { + // add all non-root aspects to their parent + childrenNames = dictionaryService.getSubAspects(cmisMapping.getAlfrescoClass(getAlfrescoName()), false); + } + + List children = new LinkedList(); + for (QName childName : childrenNames) + { + if (cmisMapping.isValidCmisSecondaryType(childName)) + { + TypeDefinitionWrapper child = registry.getTypeDefByQName(childName); + + if (child == null) + { + throw new AlfrescoRuntimeException("Failed to retrieve sub type for type id " + childName + + " for parent type " + getAlfrescoName() + "!"); + } + children.add(child); + } + else + { + logger.info("Not a secondary type: " + childName); + } + } + + return children; +// registry.setChildren(typeDef.getId(), children); + } + + public void resolveInheritance(CMISMapping cmisMapping, + CMISDictionaryRegistry registry, DictionaryService dictionaryService) + { + PropertyDefinition propertyDefintion; + + if (parent != null) + { + for (PropertyDefinitionWrapper propDef : parent.getProperties(false)) + { + if (propertiesById.containsKey(propDef.getPropertyId())) + { + continue; + } + + org.alfresco.service.cmr.dictionary.PropertyDefinition alfrescoPropDef = dictionaryService.getProperty( + propDef.getOwningType().getAlfrescoName(), propDef.getAlfrescoName()); + + propertyDefintion = createPropertyDefinition(cmisMapping, propDef.getPropertyId(), + alfrescoPropDef.getName(), dictionaryService, alfrescoPropDef, true); + + if (propertyDefintion != null) + { + registerProperty(new BasePropertyDefintionWrapper(propertyDefintion, alfrescoPropDef.getName(), + propDef.getOwningType(), propDef.getPropertyAccessor(), propDef.getPropertyLuceneBuilder())); + } + } + } + + List children = registry.getChildren(typeDef.getId()); + for (TypeDefinitionWrapper child : children) + { + if (child instanceof AbstractTypeDefinitionWrapper) + { + ((AbstractTypeDefinitionWrapper) child).resolveInheritance(cmisMapping, registry, + dictionaryService); + } + } + } + + @Override + public void updateDefinition(DictionaryService dictionaryService) + { + AspectDefinition aspectDef = dictionaryService.getAspect(alfrescoName); + + if (aspectDef != null) + { + setTypeDefDisplayName(aspectDef.getTitle(dictionaryService)); + setTypeDefDescription(aspectDef.getDescription(dictionaryService)); + } + else + { + super.updateDefinition(dictionaryService); + } + + updateTypeDefInclProperties(); + } + + @Override + public PropertyDefinitionWrapper getPropertyById(String propertyId) + { + updateProperty(dictionaryService, propertiesById.get(propertyId)); + return propertiesById.get(propertyId); + } + + @Override + public Collection getProperties() + { + updateProperties(dictionaryService); + return propertiesById.values(); + } + + @Override + public Collection getProperties(boolean update) + { + if (update) + { + return getProperties(); + } + else + { + return propertiesById.values(); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/ShadowTypeDefinitionWrapper.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/ShadowTypeDefinitionWrapper.java new file mode 100644 index 0000000000..29e628418c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/ShadowTypeDefinitionWrapper.java @@ -0,0 +1,137 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.opencmis.mapping.CMISMapping; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.namespace.QName; +import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition; + +public abstract class ShadowTypeDefinitionWrapper extends AbstractTypeDefinitionWrapper +{ + + private static final long serialVersionUID = 1L; + + @Override + public List connectParentAndSubTypes(CMISMapping cmisMapping, CMISDictionaryRegistry registry, + DictionaryService dictionaryService) + { + String parentTypeId = typeDef.getParentTypeId(); + + // find parent + if (parentTypeId != null) + { + parent = registry.getTypeDefByTypeId(parentTypeId); + if(registry.getTenant() != null && parent != null && registry.getTypeDefByTypeId(parentTypeId, false) == null) + { + // this is a tenant registry and the parent is not defined locally so add this type as a child of it + registry.addChild(parent.getTypeId(), this); + } + } + else + { + if (!isBaseType()) + { + throw new AlfrescoRuntimeException("Type " + typeDef.getId() + " has no parent!"); + } + + parent = null; + } + +// if(parent != null) +// { +// List children = new LinkedList(); +// children.add(this); +// registry.setChildren(parent.getTypeId(), children); +// } + + // find children +// children = new ArrayList(); + List children = new LinkedList(); + Collection childrenNames = dictionaryService.getSubTypes(cmisMapping.getAlfrescoClass(getAlfrescoName()), + false); + for (QName childName : childrenNames) + { + if (cmisMapping.isValidCmisObject(getBaseTypeId(), childName)) + { + TypeDefinitionWrapper child = registry.getTypeDefByQName(childName); + + if (child == null) + { + throw new AlfrescoRuntimeException("Failed to retrieve sub type for type id " + childName + + " for parent type " + getAlfrescoName() + "!"); + } + children.add(child); + } + } + return children; +// registry.setChildren(typeDef.getId(), children); + } + + public void resolveInheritance(CMISMapping cmisMapping, + CMISDictionaryRegistry registry, DictionaryService dictionaryService) + { + PropertyDefinition propertyDefintion; + + if (parent != null) + { + for (PropertyDefinitionWrapper propDef : parent.getProperties(false)) + { + if (propertiesById.containsKey(propDef.getPropertyId())) + { + continue; + } + + org.alfresco.service.cmr.dictionary.PropertyDefinition alfrescoPropDef = dictionaryService.getProperty( + propDef.getOwningType().getAlfrescoName(), propDef.getAlfrescoName()); + + propertyDefintion = createPropertyDefinition(cmisMapping, propDef.getPropertyId(), + alfrescoPropDef.getName(), dictionaryService, alfrescoPropDef, true); + + if (propertyDefintion != null) + { + registerProperty(new BasePropertyDefintionWrapper(propertyDefintion, alfrescoPropDef.getName(), + propDef.getOwningType(), propDef.getPropertyAccessor(), propDef.getPropertyLuceneBuilder())); + } + } + } + + List children = registry.getChildren(typeDef.getId()); + for (TypeDefinitionWrapper child : children) + { + if (child instanceof AbstractTypeDefinitionWrapper) + { + ((AbstractTypeDefinitionWrapper) child).resolveInheritance(cmisMapping, registry, + dictionaryService); + } + } + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/dictionary/TypeDefinitionWrapper.java b/data-model/src/main/java/org/alfresco/opencmis/dictionary/TypeDefinitionWrapper.java new file mode 100644 index 0000000000..59a2f1ea28 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/dictionary/TypeDefinitionWrapper.java @@ -0,0 +1,69 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.namespace.QName; +import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition; +import org.apache.chemistry.opencmis.commons.enums.Action; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; + +public interface TypeDefinitionWrapper +{ + TypeDefinition getTypeDefinition(boolean includePropertyDefinitions); + + String getTypeId(); + + BaseTypeId getBaseTypeId(); + + boolean isBaseType(); + + QName getAlfrescoName(); + + QName getAlfrescoClass(); + String getTenantId(); + TypeDefinitionWrapper getParent(); + +// List getChildren(); + + Collection getProperties(); + + Collection getProperties(boolean update); + + PropertyDefinitionWrapper getPropertyById(String propertyId); + + PropertyDefinitionWrapper getPropertyByQueryName(String queryName); + + PropertyDefinitionWrapper getPropertyByQName(QName name); + + Map getActionEvaluators(); + + void updateDefinition(DictionaryService dictionaryService); +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/mapping/AbstractSimpleLuceneBuilder.java b/data-model/src/main/java/org/alfresco/opencmis/mapping/AbstractSimpleLuceneBuilder.java new file mode 100644 index 0000000000..91b1f34d8b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/mapping/AbstractSimpleLuceneBuilder.java @@ -0,0 +1,138 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.mapping; + +import java.io.Serializable; + +import org.alfresco.repo.search.adaptor.lucene.AnalysisMode; +import org.alfresco.repo.search.adaptor.lucene.LuceneFunction; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.namespace.QName; + +/** + * Common support for lucene query building. + * + * @author davidc + */ +public abstract class AbstractSimpleLuceneBuilder extends BaseLuceneBuilder +{ + /** + * Construct + */ + protected AbstractSimpleLuceneBuilder() + { + super(); + } + + protected abstract String getValueAsString(Serializable value); + + protected String getRangeMax() + { + return "\uFFFF"; + } + + protected String getRangeMin() + { + return "\u0000"; + } + + protected abstract DataTypeDefinition getInDataType(); + + protected abstract QName getQNameForExists(); + + @Override + public Q buildLuceneEquality(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + return lqpa.getFieldQuery(getLuceneFieldName(), getValueAsString(value), AnalysisMode.IDENTIFIER, luceneFunction); + } + + @Override + public Q buildLuceneExists(LuceneQueryParserAdaptor lqpa, Boolean not) throws E + { + if (not) + { + return lqpa.getFieldQuery("ISNULL", getQNameForExists().toString(), AnalysisMode.DEFAULT, LuceneFunction.FIELD); + } + else + { + return lqpa.getFieldQuery("ISNOTNULL", getQNameForExists().toString(), AnalysisMode.DEFAULT, LuceneFunction.FIELD); + } + } + + @Override + public Q buildLuceneGreaterThan(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + String field = getLuceneFieldName(); + String stringValue = getValueAsString(value); + return lqpa.getRangeQuery(field, stringValue, getRangeMax(), false, true, AnalysisMode.IDENTIFIER, luceneFunction); + } + + @Override + public Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + String field = getLuceneFieldName(); + String stringValue = getValueAsString(value); + return lqpa.getRangeQuery(field, stringValue, getRangeMax(), true, true, AnalysisMode.IDENTIFIER, luceneFunction); + } + + @Override + public Q buildLuceneLessThan(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + String field = getLuceneFieldName(); + String stringValue = getValueAsString(value); + return lqpa.getRangeQuery(field, getRangeMin(), stringValue, true, false, AnalysisMode.IDENTIFIER, luceneFunction); + } + + @Override + public Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + String field = getLuceneFieldName(); + String stringValue = getValueAsString(value); + return lqpa.getRangeQuery(field, getRangeMin(), stringValue, true, true, AnalysisMode.IDENTIFIER, luceneFunction); + } + + @Override + public Q buildLuceneLike(LuceneQueryParserAdaptor lqpa, Serializable value, Boolean not) throws E + { + String field = getLuceneFieldName(); + String stringValue = getValueAsString(value); + + Q q = lqpa.getLikeQuery(field, stringValue, AnalysisMode.IDENTIFIER); + if (not) + { + q = lqpa.getNegatedQuery(q); + } + return q; + } + + @Override + public String getLuceneSortField(LuceneQueryParserAdaptor lqpa) throws E + { + return getLuceneFieldName(); + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/mapping/BaseLuceneBuilder.java b/data-model/src/main/java/org/alfresco/opencmis/mapping/BaseLuceneBuilder.java new file mode 100644 index 0000000000..ddb8e15a31 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/mapping/BaseLuceneBuilder.java @@ -0,0 +1,129 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.mapping; + +import java.io.Serializable; +import java.util.Collection; + +import org.alfresco.opencmis.dictionary.CMISPropertyLuceneBuilder; +import org.alfresco.repo.search.adaptor.lucene.LuceneFunction; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserExpressionAdaptor; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; + +/** + * Base class for all property lucene builders + * + * @author davidc + */ +public class BaseLuceneBuilder implements CMISPropertyLuceneBuilder +{ + /** + * Construct + * + */ + protected BaseLuceneBuilder() + { + } + + @Override + public Q buildLuceneEquality(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + throw new UnsupportedOperationException(); + } + + @Override + public Q buildLuceneExists(LuceneQueryParserAdaptor lqpa, Boolean not) throws E + { + throw new UnsupportedOperationException(); + } + + @Override + public Q buildLuceneGreaterThan(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + throw new UnsupportedOperationException(); + } + + @Override + public Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + throw new UnsupportedOperationException(); + } + + @Override + public Q buildLuceneIn(LuceneQueryParserAdaptor lqpa, Collection values, Boolean not, PredicateMode mode) throws E + { + LuceneQueryParserExpressionAdaptor expressionAdaptor = lqpa.getExpressionAdaptor(); + for(Serializable value : values) + { + expressionAdaptor.addOptional(buildLuceneEquality(lqpa, value, mode, LuceneFunction.FIELD)); + } + if(not) + { + return expressionAdaptor.getNegatedQuery(); + } + else + { + return expressionAdaptor.getQuery(); + } + } + + @Override + public Q buildLuceneInequality(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + return lqpa.getNegatedQuery(buildLuceneEquality(lqpa, value, mode, luceneFunction)); + } + + @Override + public Q buildLuceneLessThan(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + throw new UnsupportedOperationException(); + } + + @Override + public Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + throw new UnsupportedOperationException(); + } + + @Override + public Q buildLuceneLike(LuceneQueryParserAdaptor lqpa, Serializable value, Boolean not) throws E + { + throw new UnsupportedOperationException(); + } + + @Override + public String getLuceneFieldName() + { + throw new UnsupportedOperationException(); + } + + @Override + public String getLuceneSortField(LuceneQueryParserAdaptor lqpa) throws E + { + throw new UnsupportedOperationException(); + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/mapping/BaseTypeIdLuceneBuilder.java b/data-model/src/main/java/org/alfresco/opencmis/mapping/BaseTypeIdLuceneBuilder.java new file mode 100644 index 0000000000..14e100e2d4 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/mapping/BaseTypeIdLuceneBuilder.java @@ -0,0 +1,100 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.mapping; + +import java.io.Serializable; + +import org.alfresco.opencmis.dictionary.CMISDictionaryService; +import org.alfresco.opencmis.dictionary.TypeDefinitionWrapper; +import org.alfresco.repo.search.adaptor.lucene.AnalysisMode; +import org.alfresco.repo.search.adaptor.lucene.LuceneFunction; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; + + +/** + * Get the CMIS object type id property + * + * @author andyh + */ +public class BaseTypeIdLuceneBuilder extends BaseLuceneBuilder +{ + private CMISDictionaryService dictionaryService; + + + /** + * Construct + */ + public BaseTypeIdLuceneBuilder(CMISDictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + @Override + public Q buildLuceneEquality(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + return lqpa.getFieldQuery("TYPE", getType(getValueAsString(value)), AnalysisMode.IDENTIFIER, luceneFunction); + } + + @Override + public Q buildLuceneExists(LuceneQueryParserAdaptor lqpa, Boolean not) throws E + { + if (not) + { + return lqpa.getMatchNoneQuery(); + } + else + { + return lqpa.getMatchAllQuery(); + } + } + + private String getType(String tableName) + { + TypeDefinitionWrapper typeDef = dictionaryService.findTypeByQueryName(tableName); + if (typeDef == null) + { + throw new CmisInvalidArgumentException("Unknown type: " + tableName); + } + if(!typeDef.isBaseType()) + { + throw new CmisInvalidArgumentException("Not a base type: " + tableName); + } + if(!typeDef.getTypeDefinition(false).isQueryable()) + { + throw new CmisInvalidArgumentException("Type is not queryable: " + tableName); + } + return typeDef.getAlfrescoClass().toString(); + } + + private String getValueAsString(Serializable value) + { + String asString = DefaultTypeConverter.INSTANCE.convert(String.class, value); + return asString; + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/mapping/CMISMapping.java b/data-model/src/main/java/org/alfresco/opencmis/mapping/CMISMapping.java new file mode 100644 index 0000000000..951d2b1bdc --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/mapping/CMISMapping.java @@ -0,0 +1,860 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.mapping; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.alfresco.model.ContentModel; +import org.alfresco.opencmis.CMISAccessControlFormatEnum; +import org.alfresco.opencmis.dictionary.QNameFilter; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.chemistry.opencmis.commons.enums.CmisVersion; +import org.apache.chemistry.opencmis.commons.enums.PropertyType; +import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; +import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException; +import org.springframework.beans.factory.InitializingBean; + +/** + * CMIS <-> Alfresco mappings. It additionally excludes a list of QNames based + * on a user defined list + * + * @author andyh + */ +public class CMISMapping implements InitializingBean +{ + + /** + * The Alfresco CMIS Namespace + */ + public static String CMIS_MODEL_NS = "cmis"; + public static String CMIS_MODEL_URI = "http://www.alfresco.org/model/cmis/1.0/cs01"; + + public static String CMIS_EXT_NS = "cmisext"; + public static String CMIS_EXT_URI = "http://www.alfresco.org/model/cmis/1.0/cs01ext"; + + /** + * The Alfresco CMIS Model name. + */ + public static String CMIS_MODEL_NAME = "cmismodel"; + + /** + * The QName for the Alfresco CMIS Model. + */ + public static QName CMIS_MODEL_QNAME = QName.createQName(CMIS_MODEL_URI, CMIS_MODEL_NAME); + + // CMIS Data Types + public static QName CMIS_DATATYPE_ID = QName.createQName(CMIS_MODEL_URI, "id"); + public static QName CMIS_DATATYPE_URI = QName.createQName(CMIS_MODEL_URI, "uri"); + public static QName CMIS_DATATYPE_XML = QName.createQName(CMIS_MODEL_URI, "xml"); + public static QName CMIS_DATATYPE_HTML = QName.createQName(CMIS_MODEL_URI, "html"); + + // CMIS Types + public static QName OBJECT_QNAME = QName.createQName(CMIS_EXT_URI, "object"); + public static QName DOCUMENT_QNAME = QName.createQName(CMIS_MODEL_URI, "document"); + public static QName FOLDER_QNAME = QName.createQName(CMIS_MODEL_URI, "folder"); + public static QName RELATIONSHIP_QNAME = QName.createQName(CMIS_MODEL_URI, "relationship"); + public static QName POLICY_QNAME = QName.createQName(CMIS_MODEL_URI, "policy"); + public static QName SECONDARY_TYPES_QNAME = QName.createQName(CMIS_MODEL_URI, "secondary"); // cmis 1.1 + public static QName ASPECTS_QNAME = QName.createQName(CMIS_EXT_URI, "aspects"); // cmis 1.0 + public static QName ITEM_QNAME = QName.createQName(CMIS_MODEL_URI, "item"); // cmis 1.1 + + // CMIS Internal Type Ids + public static String OBJECT_TYPE_ID = "cmisext:object"; + + /** + * Basic permissions. + */ + public static final String CMIS_READ = "cmis:read"; + public static final String CMIS_WRITE = "cmis:write"; + public static final String CMIS_ALL = "cmis:all"; + + // Service Dependencies + protected DictionaryService dictionaryService; + protected NamespaceService namespaceService; + + // Mappings + private Map mapAlfrescoQNameToTypeId = new HashMap(); + private Map mapCmisQNameToAlfrescoQName = new HashMap(); + private Map mapAlfrescoQNameToCmisQName = new HashMap(); + private Map mapAlfrescoToCmisDataType = new HashMap(); + private Map mapCmisDataTypeToAlfresco = new HashMap(); + + private QNameFilter filter; + + private CmisVersion cmisVersion; + + public void setCmisVersion(CmisVersion cmisVersion) + { + this.cmisVersion = cmisVersion; + } + + public CmisVersion getCmisVersion() + { + return cmisVersion; + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() + { + // + // Type Mappings + // + + mapAlfrescoQNameToTypeId.put(OBJECT_QNAME, OBJECT_TYPE_ID); + mapAlfrescoQNameToTypeId.put(DOCUMENT_QNAME, BaseTypeId.CMIS_DOCUMENT.value()); + mapAlfrescoQNameToTypeId.put(FOLDER_QNAME, BaseTypeId.CMIS_FOLDER.value()); + mapAlfrescoQNameToTypeId.put(RELATIONSHIP_QNAME, BaseTypeId.CMIS_RELATIONSHIP.value()); + mapAlfrescoQNameToTypeId.put(SECONDARY_TYPES_QNAME, BaseTypeId.CMIS_SECONDARY.value()); + mapAlfrescoQNameToTypeId.put(ITEM_QNAME, BaseTypeId.CMIS_ITEM.value()); + mapAlfrescoQNameToTypeId.put(POLICY_QNAME, BaseTypeId.CMIS_POLICY.value()); + + mapAlfrescoQNameToCmisQName.put(ContentModel.TYPE_CONTENT, DOCUMENT_QNAME); + mapAlfrescoQNameToCmisQName.put(ContentModel.TYPE_FOLDER, FOLDER_QNAME); + mapAlfrescoQNameToCmisQName.put(ContentModel.TYPE_BASE, ITEM_QNAME); + + mapCmisQNameToAlfrescoQName.put(DOCUMENT_QNAME, ContentModel.TYPE_CONTENT); + mapCmisQNameToAlfrescoQName.put(FOLDER_QNAME, ContentModel.TYPE_FOLDER); + mapCmisQNameToAlfrescoQName.put(ITEM_QNAME, ContentModel.TYPE_BASE); + mapCmisQNameToAlfrescoQName.put(RELATIONSHIP_QNAME, null); + mapCmisQNameToAlfrescoQName.put(POLICY_QNAME, null); + + // + // Data Type Mappings + // + + mapAlfrescoToCmisDataType.put(DataTypeDefinition.ANY, null); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.ENCRYPTED, null); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.ASSOC_REF, null); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.BOOLEAN, PropertyType.BOOLEAN); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.CATEGORY, PropertyType.ID); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.CHILD_ASSOC_REF, null); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.CONTENT, null); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.DATE, PropertyType.DATETIME); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.DATETIME, PropertyType.DATETIME); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.DOUBLE, PropertyType.DECIMAL); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.FLOAT, PropertyType.DECIMAL); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.INT, PropertyType.INTEGER); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.LOCALE, null); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.PERIOD, null); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.LONG, PropertyType.INTEGER); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.MLTEXT, PropertyType.STRING); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.NODE_REF, PropertyType.ID); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.PATH, null); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.QNAME, null); + mapAlfrescoToCmisDataType.put(DataTypeDefinition.TEXT, PropertyType.STRING); + mapAlfrescoToCmisDataType.put(CMIS_DATATYPE_ID, PropertyType.ID); + mapAlfrescoToCmisDataType.put(CMIS_DATATYPE_URI, PropertyType.URI); + mapAlfrescoToCmisDataType.put(CMIS_DATATYPE_HTML, PropertyType.HTML); + + mapCmisDataTypeToAlfresco.put(PropertyType.ID, DataTypeDefinition.TEXT); + mapCmisDataTypeToAlfresco.put(PropertyType.INTEGER, DataTypeDefinition.LONG); + mapCmisDataTypeToAlfresco.put(PropertyType.STRING, DataTypeDefinition.TEXT); + mapCmisDataTypeToAlfresco.put(PropertyType.DECIMAL, DataTypeDefinition.DOUBLE); + mapCmisDataTypeToAlfresco.put(PropertyType.BOOLEAN, DataTypeDefinition.BOOLEAN); + mapCmisDataTypeToAlfresco.put(PropertyType.DATETIME, DataTypeDefinition.DATETIME); + mapCmisDataTypeToAlfresco.put(PropertyType.URI, DataTypeDefinition.TEXT); + mapCmisDataTypeToAlfresco.put(PropertyType.HTML, DataTypeDefinition.TEXT); + } + + public void setFilter(QNameFilter filter) + { + this.filter = filter; + } + + /** + * @param dictionaryService dictionaryService + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + /** + * @param namespaceService service + */ + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + + /** + * @return namespaceService + */ + public NamespaceService getNamespaceService() + { + return namespaceService; + } + + /** + * @return dictionaryService + */ + public DictionaryService getDictionaryService() + { + return dictionaryService; + } + + /* + * Is the type excluded from the CMIS dictionary and therefore not visible to clients? + */ + public boolean isExcluded(QName typeQName) + { + boolean isExcluded = false; + + // check for exclusion of the type and, if necessary, its parents + if(filter != null && typeQName != null) + { + isExcluded = filter.isExcluded(typeQName); + if(!isExcluded) + { + + // check parent, if any + AspectDefinition aspectDef = dictionaryService.getAspect(typeQName); + QName parentType = null; + if(aspectDef != null) + { + parentType = aspectDef.getParentName(); + } + else + { + TypeDefinition typeDef = dictionaryService.getType(typeQName); + if(typeDef != null) + { + parentType = typeDef.getParentName(); + } + else + { + parentType = null; + } + } + if(parentType != null) + { + isExcluded = isExcluded(parentType); + } + } + + filter.setExcluded(typeQName, Boolean.valueOf(isExcluded)); + } + + return isExcluded; + } + + /** + * Gets the CMIS Type Id given the Alfresco QName for the type in any + * Alfresco model + * + * @param scope BaseTypeId + * @param typeQName QName + * @return String + */ + public String getCmisTypeId(BaseTypeId scope, QName typeQName) + { + String typeId = mapAlfrescoQNameToTypeId.get(typeQName); + if (typeId == null) + { + String p = null; + switch (scope) + { + case CMIS_DOCUMENT: + p = "D"; + break; + case CMIS_FOLDER: + p = "F"; + break; + case CMIS_RELATIONSHIP: + p = "R"; + break; + case CMIS_SECONDARY: + p = "P"; + break; + case CMIS_POLICY: + p = "P"; + break; + case CMIS_ITEM: + p = "I"; + break; + default: + throw new CmisRuntimeException("Invalid base type!"); + } + + return p + ":" + typeQName.toPrefixString(namespaceService); + } + else + { + return typeId; + } + } + + public String getCmisTypeId(QName classQName) + { + if (classQName.equals(ContentModel.TYPE_CONTENT)) + { + return getCmisTypeId(BaseTypeId.CMIS_DOCUMENT, classQName); + } + if (classQName.equals(ContentModel.TYPE_FOLDER)) + { + return getCmisTypeId(BaseTypeId.CMIS_FOLDER, classQName); + } + if (classQName.equals(CMISMapping.RELATIONSHIP_QNAME)) + { + return getCmisTypeId(BaseTypeId.CMIS_RELATIONSHIP, classQName); + } + if (classQName.equals(CMISMapping.POLICY_QNAME)) + { + return getCmisTypeId(BaseTypeId.CMIS_POLICY, classQName); + } + if (classQName.equals(CMISMapping.ASPECTS_QNAME)) + { + return getCmisTypeId(BaseTypeId.CMIS_POLICY, classQName); + } + if (isValidCmisDocument(classQName)) + { + return getCmisTypeId(BaseTypeId.CMIS_DOCUMENT, classQName); + } + if (isValidCmisFolder(classQName)) + { + return getCmisTypeId(BaseTypeId.CMIS_FOLDER, classQName); + } + if (isValidCmisRelationship(classQName)) + { + return getCmisTypeId(BaseTypeId.CMIS_RELATIONSHIP, classQName); + } + if (cmisVersion.equals(CmisVersion.CMIS_1_1) && isValidCmisSecondaryType(classQName)) + { + return getCmisTypeId(BaseTypeId.CMIS_SECONDARY, classQName); + } + if (cmisVersion.equals(CmisVersion.CMIS_1_1) && isValidCmisItem(classQName)) + { + return getCmisTypeId(BaseTypeId.CMIS_ITEM, classQName); + } + if (cmisVersion.equals(CmisVersion.CMIS_1_0) && isValidCmisPolicy(classQName)) + { + return getCmisTypeId(BaseTypeId.CMIS_POLICY, classQName); + } + + return null; + } + + public String buildPrefixEncodedString(QName qname) + { + return qname.toPrefixString(namespaceService); + } + + public QName getAlfrescoName(String typeId) + { + // Is it an Alfresco type id? + if (typeId.length() < 4 || typeId.charAt(1) != ':') + { + throw new CmisInvalidArgumentException("Malformed type id '" + typeId + "'"); + } + + return QName.createQName(typeId.substring(2), namespaceService); + } + + public boolean isValidCmisObject(BaseTypeId scope, QName qname) + { + switch (scope) + { + case CMIS_DOCUMENT: + return isValidCmisDocument(qname); + case CMIS_FOLDER: + return isValidCmisFolder(qname); + case CMIS_POLICY: + return isValidCmisPolicy(qname); + case CMIS_RELATIONSHIP: + return isValidCmisRelationship(qname); + case CMIS_SECONDARY: + return isValidCmisSecondaryType(qname); + case CMIS_ITEM: + return isValidCmisItem(qname); + } + + return false; + } + + /** + * Is this a valid CMIS folder type? + * + * @param typeQName QName + * @return boolean + */ + public boolean isValidCmisFolder(QName typeQName) + { + if(isExcluded(typeQName)) + { + return false; + } + + if (typeQName == null) + { + return false; + } + if (typeQName.equals(FOLDER_QNAME)) + { + return true; + } + + if (dictionaryService.isSubClass(typeQName, ContentModel.TYPE_FOLDER)) + { + if (typeQName.equals(ContentModel.TYPE_FOLDER)) + { + return false; + } else + { + return true; + } + } + + return false; + } + + /** + * Is this a valid CMIS document type? + * + * @param typeQName QName + * @return boolean + */ + public boolean isValidCmisDocument(QName typeQName) + { + if(isExcluded(typeQName)) + { + return false; + } + + if (typeQName == null) + { + return false; + } + if (typeQName.equals(DOCUMENT_QNAME)) + { + return true; + } + + if (dictionaryService.isSubClass(typeQName, ContentModel.TYPE_CONTENT)) + { + if (typeQName.equals(ContentModel.TYPE_CONTENT)) + { + return false; + } else + { + return true; + } + } + return false; + } + + /** + * Is this a valid CMIS secondary type? + * + * @param typeQName QName + * @return boolean + */ + public boolean isValidCmisSecondaryType(QName typeQName) + { + if(isExcluded(typeQName)) + { + return false; + } + + if (typeQName == null) + { + return false; + } + + if (typeQName.equals(SECONDARY_TYPES_QNAME)) + { + return true; + } + + AspectDefinition aspectDef = dictionaryService.getAspect(typeQName); + if (aspectDef == null) + { + return false; + } + + // Anything derived from the aspects here would at some point have to linked up with an invalid parent so exclude these aspects + // AND any that are derived from them. + if ( dictionaryService.isSubClass(aspectDef.getName(), ContentModel.ASPECT_VERSIONABLE) + || dictionaryService.isSubClass(aspectDef.getName(), ContentModel.ASPECT_AUDITABLE) + || dictionaryService.isSubClass(aspectDef.getName(), ContentModel.ASPECT_REFERENCEABLE)) + { + return false; + } + return true; + } + + /** + * Is this a valid CMIS policy type? + * + * @param typeQName QName + * @return boolean + */ + public boolean isValidCmisPolicy(QName typeQName) + { if (typeQName == null) + { + return false; + } + if (typeQName.equals(POLICY_QNAME)) + { + return true; + } + + if(cmisVersion.equals(CmisVersion.CMIS_1_0)) + { + if (typeQName.equals(ASPECTS_QNAME)) + { + return true; + } + + AspectDefinition aspectDef = dictionaryService.getAspect(typeQName); + if (aspectDef == null) + { + return false; + } + + // Anything derived from the aspects here would at some point have to linked up with an invalid parent so exclude these aspects + // AND any that are derived from them. + if ( dictionaryService.isSubClass(aspectDef.getName(), ContentModel.ASPECT_VERSIONABLE) + || dictionaryService.isSubClass(aspectDef.getName(), ContentModel.ASPECT_AUDITABLE) + || dictionaryService.isSubClass(aspectDef.getName(), ContentModel.ASPECT_REFERENCEABLE)) + { + return false; + } + return true; + } + else + { + return false; + } + } + + /** + * Is an association valid in CMIS? It must be a non-child relationship and + * the source and target must both be valid CMIS types. + * + * @param associationQName QName + * @return boolean + */ + public boolean isValidCmisRelationship(QName associationQName) + { + if (associationQName == null) + { + return false; + } + if (associationQName.equals(RELATIONSHIP_QNAME)) + { + return true; + } + AssociationDefinition associationDefinition = dictionaryService.getAssociation( + associationQName); + if (associationDefinition == null) + { + return false; + } + if (associationDefinition.isChild()) + { + return false; + } + if(!isValidCmisRelationshipEndPoint(associationDefinition.getTargetClass().getName())) + { + return false; + } + if(!isValidCmisRelationshipEndPoint(associationDefinition.getSourceClass().getName())) + { + return false; + } + return true; + } + + public boolean isValidCmisRelationshipEndPoint(QName typeQName) + { + if(dictionaryService.getClass(typeQName).isAspect()) + { + return true; + } + + if (typeQName.equals(FOLDER_QNAME)) + { + return true; + } + + + if (typeQName.equals(DOCUMENT_QNAME)) + { + return true; + } + + if (dictionaryService.isSubClass(typeQName, ContentModel.TYPE_BASE)) + { + return true; + } + return false; + } + + /** + * Is this a valid CMIS item type? + * + * @param typeQName QName + * @return boolean + */ + public boolean isValidCmisItem(QName typeQName) + { + if(isExcluded(typeQName)) + { + return false; + } + + if (typeQName == null) + { + return false; + } + + if(typeQName.equals(ITEM_QNAME)) + { + return true; + } + + if(typeQName.equals(ContentModel.TYPE_BASE)) + { + return false; + } + + AspectDefinition aspectDef = dictionaryService.getAspect(typeQName); + if (aspectDef != null) + { + // aspects are not items - this stops warning from getType + return false; + } + + TypeDefinition typeDef = dictionaryService.getType(typeQName); + if (typeDef == null) + { + // type does not exist + return false; + } + + if (dictionaryService.isSubClass(typeQName, ContentModel.TYPE_BASE)) + { + if(dictionaryService.isSubClass(typeQName, ContentModel.TYPE_FOLDER)) + { + return false; + } + if(dictionaryService.isSubClass(typeQName, ContentModel.TYPE_CONTENT)) + { + return false; + } + + return true; + } + + return false; + } + + + + /** + * Given an Alfresco model type map it to the appropriate type. Maps + * cm:folder and cm:content to the CMIS definitions + */ + public QName getCmisType(QName typeQName) + { + QName mapped = mapAlfrescoQNameToCmisQName.get(typeQName); + if (mapped != null) + { + return mapped; + } + return typeQName; + } + + /** + * Is Alfresco Type mapped to an alternative CMIS Type? + */ + public boolean isRemappedType(QName typeQName) + { + return mapAlfrescoQNameToCmisQName.containsKey(typeQName); + } + + /** + * Given a CMIS model type map it to the appropriate Alfresco type. + * + * @param cmisTypeQName QName + * @return QName + */ + public QName getAlfrescoClass(QName cmisTypeQName) + { + QName mapped = mapCmisQNameToAlfrescoQName.get(cmisTypeQName); + if (mapped != null) + { + return mapped; + } + return cmisTypeQName; + } + + /** + * Get the CMIS property type for a property + * + * @param datatype DataTypeDefinition + * @return PropertyType + */ + public PropertyType getDataType(DataTypeDefinition datatype) + { + return getDataType(datatype.getName()); + } + + public PropertyType getDataType(QName dataType) + { + return mapAlfrescoToCmisDataType.get(dataType); + } + + public QName getAlfrescoDataType(PropertyType propertyType) + { + return mapCmisDataTypeToAlfresco.get(propertyType); + } + + /** + * @param propertyQName QName + * @return String + */ + public String getCmisPropertyId(QName propertyQName) + { + return propertyQName.toPrefixString(namespaceService); + } + + public Collection> getReportedPermissions(String permission, Set permissions, + boolean hasFull, boolean isDirect, CMISAccessControlFormatEnum format) + { + ArrayList> answer = new ArrayList>(20); + // indirect + + if (hasFull) + { + answer.add(new Pair(CMIS_READ, false)); + answer.add(new Pair(CMIS_WRITE, false)); + answer.add(new Pair(CMIS_ALL, false)); + } + + for (String perm : permissions) + { + if (PermissionService.READ.equals(perm)) + { + answer.add(new Pair(CMIS_READ, false)); + } else if (PermissionService.WRITE.equals(perm)) + { + answer.add(new Pair(CMIS_WRITE, false)); + } else if (PermissionService.ALL_PERMISSIONS.equals(perm)) + { + answer.add(new Pair(CMIS_READ, false)); + answer.add(new Pair(CMIS_WRITE, false)); + answer.add(new Pair(CMIS_ALL, false)); + } + + if (hasFull) + { + answer.add(new Pair(CMIS_READ, false)); + answer.add(new Pair(CMIS_WRITE, false)); + answer.add(new Pair(CMIS_ALL, false)); + } + } + + // permission + + if (format == CMISAccessControlFormatEnum.REPOSITORY_SPECIFIC_PERMISSIONS) + { + if (PermissionService.READ.equals(permission)) + { + answer.add(new Pair(CMIS_READ, false)); + answer.add(new Pair(permission, isDirect)); + } else if (PermissionService.WRITE.equals(permission)) + { + answer.add(new Pair(CMIS_WRITE, false)); + answer.add(new Pair(permission, isDirect)); + } else if (PermissionService.ALL_PERMISSIONS.equals(permission)) + { + answer.add(new Pair(CMIS_ALL, false)); + answer.add(new Pair(permission, isDirect)); + } else + { + answer.add(new Pair(permission, isDirect)); + } + } else if (format == CMISAccessControlFormatEnum.CMIS_BASIC_PERMISSIONS) + { + if (PermissionService.READ.equals(permission)) + { + answer.add(new Pair(CMIS_READ, isDirect)); + } else if (PermissionService.WRITE.equals(permission)) + { + answer.add(new Pair(CMIS_WRITE, isDirect)); + } else if (PermissionService.ALL_PERMISSIONS.equals(permission)) + { + answer.add(new Pair(CMIS_ALL, isDirect)); + } else + { + // else nothing + } + } + + return answer; + } + + /** + * @param permission String + * @return permission to set + */ + public String getSetPermission(String permission) + { + if (permission.equals(CMIS_READ)) + { + return PermissionService.READ; + } else if (permission.equals(CMIS_WRITE)) + { + return PermissionService.WRITE; + } else if (permission.equals(CMIS_ALL)) + { + return PermissionService.ALL_PERMISSIONS; + } else + { + return permission; + } + } + +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/mapping/ContentStreamLengthLuceneBuilder.java b/data-model/src/main/java/org/alfresco/opencmis/mapping/ContentStreamLengthLuceneBuilder.java new file mode 100644 index 0000000000..3b8e58e70e --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/mapping/ContentStreamLengthLuceneBuilder.java @@ -0,0 +1,85 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.mapping; + +import java.io.Serializable; + +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.service.namespace.QName; + +/** + * Lucene Builder for CMIS content stream length property + * + * @author andyh + */ +public class ContentStreamLengthLuceneBuilder extends AbstractSimpleLuceneBuilder +{ + private DictionaryService dictionaryService; + + /** + * Construct + * + * @param dictionaryService DictionaryService + */ + public ContentStreamLengthLuceneBuilder(DictionaryService dictionaryService) + { + super(); + this.dictionaryService = dictionaryService; + } + + @Override + public String getLuceneFieldName() + { + StringBuilder field = new StringBuilder(128); + field.append("@"); + field.append(ContentModel.PROP_CONTENT); + field.append(".size"); + return field.toString(); + } + + @Override + protected String getValueAsString(Serializable value) + { + Object converted = DefaultTypeConverter.INSTANCE.convert(dictionaryService.getDataType(DataTypeDefinition.LONG), value); + String asString = DefaultTypeConverter.INSTANCE.convert(String.class, converted); + return asString; + } + + @Override + protected QName getQNameForExists() + { + return ContentModel.PROP_CONTENT; + } + + @Override + protected DataTypeDefinition getInDataType() + { + return dictionaryService.getDataType(DataTypeDefinition.LONG); + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/mapping/ContentStreamMimetypeLuceneBuilder.java b/data-model/src/main/java/org/alfresco/opencmis/mapping/ContentStreamMimetypeLuceneBuilder.java new file mode 100644 index 0000000000..89faca9ee1 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/mapping/ContentStreamMimetypeLuceneBuilder.java @@ -0,0 +1,85 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.mapping; + +import java.io.Serializable; + +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.service.namespace.QName; + +/** + * Lucene Builder for CMIS content stream mimetype property + * + * @author andyh + */ +public class ContentStreamMimetypeLuceneBuilder extends AbstractSimpleLuceneBuilder +{ + private DictionaryService dictionaryService; + + /** + * Construct + * + * @param dictionaryService DictionaryService + */ + public ContentStreamMimetypeLuceneBuilder(DictionaryService dictionaryService) + { + super(); + this.dictionaryService = dictionaryService; + } + + @Override + public String getLuceneFieldName() + { + StringBuilder field = new StringBuilder(128); + field.append("@"); + field.append(ContentModel.PROP_CONTENT); + field.append(".mimetype"); + return field.toString(); + } + + @Override + protected String getValueAsString(Serializable value) + { + Object converted = DefaultTypeConverter.INSTANCE.convert(dictionaryService.getDataType(DataTypeDefinition.TEXT), value); + String asString = DefaultTypeConverter.INSTANCE.convert(String.class, converted); + return asString; + } + + @Override + protected QName getQNameForExists() + { + return ContentModel.PROP_CONTENT; + } + + @Override + protected DataTypeDefinition getInDataType() + { + return dictionaryService.getDataType(DataTypeDefinition.TEXT); + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/mapping/DirectLuceneBuilder.java b/data-model/src/main/java/org/alfresco/opencmis/mapping/DirectLuceneBuilder.java new file mode 100644 index 0000000000..37c24370ae --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/mapping/DirectLuceneBuilder.java @@ -0,0 +1,143 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.mapping; + +import java.io.Serializable; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.service.namespace.QName; +import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; + +/** + * A simple 1-1 property lucene builder mapping from a CMIS property name to an alfresco property + * + * @author andyh + */ +public class DirectLuceneBuilder extends AbstractSimpleLuceneBuilder +{ + private DictionaryService dictionaryService; + private QName alfrescoName; + + public DirectLuceneBuilder(DictionaryService dictionaryService, QName alfrescoName) + { + this.dictionaryService = dictionaryService; + this.alfrescoName = alfrescoName; + } + + @Override + public String getLuceneSortField(LuceneQueryParserAdaptor lqpa) throws E + { + String field = getLuceneFieldName(); + // need to find the real field to use + PropertyDefinition propertyDef = dictionaryService.getProperty(QName.createQName(field.substring(1))); + + if (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) + { + throw new CmisInvalidArgumentException("Order on content properties is not curently supported"); + } + else if ((propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT)) || (propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT))) + { + field = lqpa.getSortField(field); + } + else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME)) + { + field = lqpa.getDatetimeSortField(field, propertyDef); + } + + return field; + } + + @Override + public String getLuceneFieldName() + { + StringBuilder field = new StringBuilder(64); + field.append("@"); + field.append(alfrescoName); + return field.toString(); + } + + @Override + protected String getValueAsString(Serializable value) + { + PropertyDefinition pd = dictionaryService.getProperty(alfrescoName); + Object converted = DefaultTypeConverter.INSTANCE.convert(pd.getDataType(), value); + String asString = DefaultTypeConverter.INSTANCE.convert(String.class, converted); + return asString; + } + + @Override + protected QName getQNameForExists() + { + return alfrescoName; + } + + @Override + protected DataTypeDefinition getInDataType() + { + PropertyDefinition pd = dictionaryService.getProperty(alfrescoName); + return pd.getDataType(); + } + + @Override + protected String getRangeMax() + { + if(getInDataType().getName().equals(DataTypeDefinition.DATE)) + { + return "MAX"; + } + else if(getInDataType().getName().equals(DataTypeDefinition.DATETIME)) + { + return "MAX"; + } + else + { + return super.getRangeMax(); + } + } + + + @Override + protected String getRangeMin() + { + if(getInDataType().getName().equals(DataTypeDefinition.DATE)) + { + return "MIN"; + } + else if(getInDataType().getName().equals(DataTypeDefinition.DATETIME)) + { + return "MIN"; + } + else + { + return super.getRangeMin(); + } + } + +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/mapping/FixedValueLuceneBuilder.java b/data-model/src/main/java/org/alfresco/opencmis/mapping/FixedValueLuceneBuilder.java new file mode 100644 index 0000000000..09c3979787 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/mapping/FixedValueLuceneBuilder.java @@ -0,0 +1,269 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.mapping; + +import java.io.Serializable; +import java.util.Collection; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.alfresco.repo.search.adaptor.lucene.LuceneFunction; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.util.EqualsHelper; +import org.alfresco.util.SearchLanguageConversion; + +/** + * Property lucene builder for fixed value mapping (eg to null, true, etc) + * + * @author andyh + */ +public class FixedValueLuceneBuilder extends BaseLuceneBuilder +{ + private Serializable value; + + /** + * Construct + * + * @param value Serializable + */ + public FixedValueLuceneBuilder(Serializable value) + { + super(); + this.value = value; + } + + @Override + public Q buildLuceneEquality(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + if (EqualsHelper.nullSafeEquals(value, value)) + { + return lqpa.getMatchAllQuery(); + } + else + { + return lqpa.getMatchNoneQuery(); + } + } + + @Override + public Q buildLuceneExists(LuceneQueryParserAdaptor lqpa, Boolean not) throws E + { + if (not) + { + if (value == null) + { + return lqpa.getMatchAllQuery(); + } + else + { + return lqpa.getMatchNoneQuery(); + } + } + else + { + if (value == null) + { + return lqpa.getMatchNoneQuery(); + } + else + { + return lqpa.getMatchAllQuery(); + } + } + + } + + @Override + @SuppressWarnings("unchecked") + public Q buildLuceneGreaterThan(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + if (value instanceof Comparable) + { + Comparable comparable = (Comparable) value; + if (comparable.compareTo(value) > 0) + { + return lqpa.getMatchAllQuery(); + } + else + { + return lqpa.getMatchNoneQuery(); + } + } + else + { + return lqpa.getMatchNoneQuery(); + } + } + + @Override + @SuppressWarnings("unchecked") + public Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + if (value instanceof Comparable) + { + Comparable comparable = (Comparable) value; + if (comparable.compareTo(value) >= 0) + { + return lqpa.getMatchAllQuery(); + } + else + { + return lqpa.getMatchNoneQuery(); + } + } + else + { + return lqpa.getMatchNoneQuery(); + } + } + + @Override + public Q buildLuceneIn(LuceneQueryParserAdaptor lqpa, Collection values, Boolean not, PredicateMode mode) throws E + { + boolean in = false; + for (Serializable value : values) + { + if (EqualsHelper.nullSafeEquals(value, value)) + { + in = true; + break; + } + } + + if (in == !not) + { + return lqpa.getMatchAllQuery(); + } + else + { + return lqpa.getMatchNoneQuery(); + } + } + + @Override + public Q buildLuceneInequality(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + if (!EqualsHelper.nullSafeEquals(value, value)) + { + return lqpa.getMatchAllQuery(); + } + else + { + return lqpa.getMatchNoneQuery(); + } + } + + @Override + @SuppressWarnings("unchecked") + public Q buildLuceneLessThan(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + if (value instanceof Comparable) + { + Comparable comparable = (Comparable) value; + if (comparable.compareTo(value) < 0) + { + return lqpa.getMatchAllQuery(); } + else + { + return lqpa.getMatchNoneQuery(); + } + } + else + { + return lqpa.getMatchNoneQuery(); + } + } + + @Override + @SuppressWarnings("unchecked") + public Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + if (value instanceof Comparable) + { + Comparable comparable = (Comparable) value; + if (comparable.compareTo(value) <= 0) + { + return lqpa.getMatchAllQuery(); + } + else + { + return lqpa.getMatchNoneQuery(); + } + } + else + { + return lqpa.getMatchNoneQuery(); + } + } + + @Override + public Q buildLuceneLike(LuceneQueryParserAdaptor lqpa, Serializable value, Boolean not) throws E + { + if (value != null) + { + boolean matches = false; + + Object converted = DefaultTypeConverter.INSTANCE.convert(value.getClass(), value); + String asString = DefaultTypeConverter.INSTANCE.convert(String.class, converted); + String regExpression = SearchLanguageConversion.convertSQLLikeToRegex(asString); + Pattern pattern = Pattern.compile(regExpression); + String target = DefaultTypeConverter.INSTANCE.convert(String.class, value); + Matcher matcher = pattern.matcher(target); + if (matcher.matches()) + { + matches = true; + } + + if (matches == !not) + { + return lqpa.getMatchAllQuery(); + } + else + { + return lqpa.getMatchNoneQuery(); + } + } + else + { + return lqpa.getMatchNoneQuery(); + } + } + + @Override + public String getLuceneSortField(LuceneQueryParserAdaptor lqpa) + { + throw new UnsupportedOperationException(); + } + + @Override + public String getLuceneFieldName() + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/mapping/NotSupportedLuceneBuilder.java b/data-model/src/main/java/org/alfresco/opencmis/mapping/NotSupportedLuceneBuilder.java new file mode 100644 index 0000000000..323f551c39 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/mapping/NotSupportedLuceneBuilder.java @@ -0,0 +1,42 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.mapping; + + +/** + * Lucene Builder for properties which do not support query + * + * @author davidc + */ +public class NotSupportedLuceneBuilder extends BaseLuceneBuilder +{ + /** + * Construct + */ + public NotSupportedLuceneBuilder() + { + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/mapping/ObjectIdLuceneBuilder.java b/data-model/src/main/java/org/alfresco/opencmis/mapping/ObjectIdLuceneBuilder.java new file mode 100644 index 0000000000..487fd1943a --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/mapping/ObjectIdLuceneBuilder.java @@ -0,0 +1,168 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.mapping; + +import java.io.Serializable; +import java.util.ArrayList; + +import org.alfresco.repo.search.adaptor.lucene.AnalysisMode; +import org.alfresco.repo.search.adaptor.lucene.LuceneFunction; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.apache.chemistry.opencmis.commons.PropertyIds; +import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; + +/** + * Lucene Builder for CMIS object id property. + * + * @author andyh + * @author dward + */ +public class ObjectIdLuceneBuilder extends BaseLuceneBuilder +{ + private DictionaryService dictionaryService; + + /** + * Construct + * + * @param dictionaryService DictionaryService + */ + public ObjectIdLuceneBuilder(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + @Override + public String getLuceneFieldName() + { + return "ID"; + } + + private StoreRef getStore(LuceneQueryParserAdaptor lqpa) + { + ArrayList stores = lqpa.getSearchParameters().getStores(); + if(stores.size() < 1) + { + // default + return StoreRef.STORE_REF_WORKSPACE_SPACESSTORE; + } + return stores.get(0); + } + + private String getValueAsString(LuceneQueryParserAdaptor lqpa, Serializable value) + { + String nodeRefStr = null; + if(!NodeRef.isNodeRef((String)value)) + { + // assume the object id is the node guid + StoreRef storeRef = getStore(lqpa); + nodeRefStr = storeRef.toString() + "/" + (String)value; + } + else + { + nodeRefStr = (String)value; + } + + Object converted = DefaultTypeConverter.INSTANCE.convert(dictionaryService.getDataType(DataTypeDefinition.NODE_REF), nodeRefStr); + String asString = DefaultTypeConverter.INSTANCE.convert(String.class, converted); + return asString; + } + + @Override + public Q buildLuceneEquality(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + String field = getLuceneFieldName(); + String stringValue = getValueAsString(lqpa, value); + return lqpa.getIdentifierQuery(field, stringValue, AnalysisMode.IDENTIFIER, luceneFunction); + } + + @Override + public Q buildLuceneExists(LuceneQueryParserAdaptor lqpa, Boolean not) throws E + { + if (not) + { + return lqpa.getMatchNoneQuery(); + } else + { + return lqpa.getMatchAllQuery(); + } + } + + @Override + public Q buildLuceneGreaterThan(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, + LuceneFunction luceneFunction) throws E + { + throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_ID + " can not be used in a 'greater than' comparison"); + } + + @Override + public Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, + LuceneFunction luceneFunction) throws E + { + throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_ID + + " can not be used in a 'greater than or equals' comparison"); + } + + @Override + public Q buildLuceneLessThan(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, + LuceneFunction luceneFunction) throws E + { + throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_ID + " can not be used in a 'less than' comparison"); + } + + @Override + public Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, + LuceneFunction luceneFunction) throws E + { + throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_ID + " can not be used in a 'less than or equals' comparison"); + } + + @Override + public Q buildLuceneLike(LuceneQueryParserAdaptor lqpa, Serializable value, Boolean not) throws E + { + String field = getLuceneFieldName(); + String stringValue = getValueAsString(lqpa, value); + + Q q = lqpa.getIdentifieLikeQuery(field, stringValue, AnalysisMode.IDENTIFIER); + if(not) + { + q = lqpa.getNegatedQuery(q); + } + return q; + } + + @Override + public String getLuceneSortField(LuceneQueryParserAdaptor lqpa) + { + return getLuceneFieldName(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/mapping/ObjectTypeIdLuceneBuilder.java b/data-model/src/main/java/org/alfresco/opencmis/mapping/ObjectTypeIdLuceneBuilder.java new file mode 100644 index 0000000000..41696c23ee --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/mapping/ObjectTypeIdLuceneBuilder.java @@ -0,0 +1,154 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.mapping; + +import java.io.Serializable; + +import org.alfresco.opencmis.dictionary.CMISDictionaryService; +import org.alfresco.opencmis.dictionary.TypeDefinitionWrapper; +import org.alfresco.repo.search.adaptor.lucene.AnalysisMode; +import org.alfresco.repo.search.adaptor.lucene.LuceneFunction; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.apache.chemistry.opencmis.commons.PropertyIds; +import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; + +/** + * Lucene Builder for CMIS object type id property + * + * @author andyh + */ +public class ObjectTypeIdLuceneBuilder extends BaseLuceneBuilder +{ + private CMISDictionaryService cmisDictionaryService; + + /** + * Construct + * + * @param cmisDictionaryService CMISDictionaryService + */ + public ObjectTypeIdLuceneBuilder(CMISDictionaryService cmisDictionaryService) + { + this.cmisDictionaryService = cmisDictionaryService; + } + + @Override + public String getLuceneFieldName() + { + return "EXACTTYPE"; + } + + private String getValueAsString(Serializable value) + { + // Object converted = + // DefaultTypeConverter.INSTANCE.convert(getServiceRegistry().getDictionaryService().getDataType(DataTypeDefinition.QNAME), + // value); + String asString = DefaultTypeConverter.INSTANCE.convert(String.class, value); + return asString; + } + + @Override + public Q buildLuceneEquality(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, + LuceneFunction luceneFunction) throws E + { + String field = getLuceneFieldName(); + String stringValue = getValueAsString(value); + TypeDefinitionWrapper type = cmisDictionaryService.findType(stringValue); + return lqpa + .getFieldQuery(field, type.getAlfrescoClass().toString(), AnalysisMode.IDENTIFIER, luceneFunction); + } + + @Override + public Q buildLuceneExists(LuceneQueryParserAdaptor lqpa, Boolean not) throws E + { + if (not) + { + return lqpa.getMatchNoneQuery(); + } else + { + return lqpa.getMatchAllQuery(); + } + } + + @Override + public Q buildLuceneGreaterThan(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, + LuceneFunction luceneFunction) throws E + { + throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_TYPE_ID + " can not be used in a 'greater than' comparison"); + } + + @Override + public Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, + LuceneFunction luceneFunction) throws E + { + throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_TYPE_ID + + " can not be used in a 'greater than or equals' comparison"); + } + + @Override + public Q buildLuceneInequality(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, + LuceneFunction luceneFunction) throws E + { + return lqpa.getNegatedQuery(buildLuceneEquality(lqpa, value, mode, luceneFunction)); + } + + @Override + public Q buildLuceneLessThan(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, + LuceneFunction luceneFunction) throws E + { + throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_TYPE_ID + " can not be used in a 'less than' comparison"); + } + + @Override + public Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, + LuceneFunction luceneFunction) throws E + { + throw new CmisInvalidArgumentException("Property " + PropertyIds.OBJECT_TYPE_ID + " can not be used in a 'less than or equals' comparison"); + } + + @Override + public Q buildLuceneLike(LuceneQueryParserAdaptor lqpa, Serializable value, Boolean not) throws E + { + String field = getLuceneFieldName(); + String stringValue = getValueAsString(value); + TypeDefinitionWrapper type = cmisDictionaryService.findType(stringValue); + String typeQName = type.getAlfrescoClass().toString(); + + Q q = lqpa.getLikeQuery(field, typeQName, AnalysisMode.IDENTIFIER); + if (not) + { + q = lqpa.getNegatedQuery(q); + } + return q; + } + + @Override + public String getLuceneSortField(LuceneQueryParserAdaptor lqpa) + { + return getLuceneFieldName(); + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/mapping/ParentLuceneBuilder.java b/data-model/src/main/java/org/alfresco/opencmis/mapping/ParentLuceneBuilder.java new file mode 100644 index 0000000000..31184f229b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/mapping/ParentLuceneBuilder.java @@ -0,0 +1,135 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.mapping; + +import java.io.Serializable; +import java.util.ArrayList; + +import org.alfresco.repo.search.adaptor.lucene.AnalysisMode; +import org.alfresco.repo.search.adaptor.lucene.LuceneFunction; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; + + +/** + * Lucene Builder for CMIS parent property + * + * @author andyh + * + */ +public class ParentLuceneBuilder extends BaseLuceneBuilder +{ + private DictionaryService dictionaryService; + + /** + * Construct + * + * @param dictionaryService DictionaryService + */ + public ParentLuceneBuilder(DictionaryService dictionaryService) + { + super(); + this.dictionaryService = dictionaryService; + } + + private StoreRef getStore(LuceneQueryParserAdaptor lqpa) + { + ArrayList stores = lqpa.getSearchParameters().getStores(); + if(stores.size() < 1) + { + // default + return StoreRef.STORE_REF_WORKSPACE_SPACESSTORE; + } + return stores.get(0); + } + + @Override + public String getLuceneFieldName() + { + return "PARENT"; + } + + private String getValueAsString(LuceneQueryParserAdaptor lqpa, Serializable value) + { + String nodeRefStr = (String)value; + if(!NodeRef.isNodeRef((String)value)) + { + // assume the value (object id) is the node guid + StoreRef storeRef = getStore(lqpa); + nodeRefStr = storeRef.toString() + "/" + (String)value; + } + + Object converted = DefaultTypeConverter.INSTANCE.convert(dictionaryService.getDataType(DataTypeDefinition.NODE_REF), nodeRefStr); + String asString = DefaultTypeConverter.INSTANCE.convert(String.class, converted); + return asString; + } + + @Override + public Q buildLuceneEquality(LuceneQueryParserAdaptor lqpa, Serializable value, PredicateMode mode, + LuceneFunction luceneFunction) throws E + { + String field = getLuceneFieldName(); + String stringValue = getValueAsString(lqpa, value); + return lqpa.getFieldQuery(field, stringValue, AnalysisMode.IDENTIFIER, luceneFunction); + } + + @Override + public Q buildLuceneExists(LuceneQueryParserAdaptor lqpa, Boolean not) throws E + { + if (not) + { + return lqpa.getFieldQuery("ISROOT", "T", AnalysisMode.IDENTIFIER, LuceneFunction.FIELD); + } else + { + return lqpa.getNegatedQuery(lqpa.getFieldQuery("ISROOT", "T", AnalysisMode.IDENTIFIER, LuceneFunction.FIELD)); + } + } + + @Override + public Q buildLuceneLike(LuceneQueryParserAdaptor lqpa, Serializable value, Boolean not) throws E + { + String field = getLuceneFieldName(); + String stringValue = getValueAsString(lqpa, value); + + Q q = lqpa.getLikeQuery(field, stringValue, AnalysisMode.IDENTIFIER); + if (not) + { + return lqpa.getNegatedQuery(q); + } + return q; + } + + @Override + public String getLuceneSortField(LuceneQueryParserAdaptor lqpa) + { + return getLuceneFieldName(); + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/mapping/RuntimePropertyLuceneBuilderMapping.java b/data-model/src/main/java/org/alfresco/opencmis/mapping/RuntimePropertyLuceneBuilderMapping.java new file mode 100644 index 0000000000..c9d610aeab --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/mapping/RuntimePropertyLuceneBuilderMapping.java @@ -0,0 +1,127 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.mapping; + +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.opencmis.dictionary.CMISDictionaryService; +import org.alfresco.opencmis.dictionary.CMISPropertyLuceneBuilder; +import org.alfresco.opencmis.dictionary.PropertyLuceneBuilderMapping; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.namespace.QName; +import org.apache.chemistry.opencmis.commons.PropertyIds; +import org.springframework.beans.factory.InitializingBean; + + +/** + * Lucene Builder mappings for built-in CMIS properties + * + * @author davidc + */ +public class RuntimePropertyLuceneBuilderMapping implements PropertyLuceneBuilderMapping, InitializingBean +{ + private CMISDictionaryService cmisDictionaryService; + private DictionaryService dictionaryService; + + private Map luceneBuilders = new HashMap(); + + /** + * @param cmisDictionaryService cmisDictionaryService + */ + public void setCmisDictionaryService(CMISDictionaryService cmisDictionaryService) + { + this.cmisDictionaryService = cmisDictionaryService; + } + + /** + * @param dictionaryService dictionaryService + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + @Override + public void afterPropertiesSet() + { + registerPropertyLuceneBuilder(PropertyIds.OBJECT_ID, new ObjectIdLuceneBuilder(dictionaryService)); + registerPropertyLuceneBuilder(PropertyIds.OBJECT_TYPE_ID, new ObjectTypeIdLuceneBuilder(cmisDictionaryService)); + registerPropertyLuceneBuilder(PropertyIds.BASE_TYPE_ID, new BaseTypeIdLuceneBuilder(cmisDictionaryService)); + registerPropertyLuceneBuilder(PropertyIds.CREATED_BY, new DirectLuceneBuilder(dictionaryService, ContentModel.PROP_CREATOR)); + registerPropertyLuceneBuilder(PropertyIds.CREATION_DATE, new DirectLuceneBuilder(dictionaryService, ContentModel.PROP_CREATED)); + registerPropertyLuceneBuilder(PropertyIds.LAST_MODIFIED_BY, new DirectLuceneBuilder(dictionaryService, ContentModel.PROP_MODIFIER)); + registerPropertyLuceneBuilder(PropertyIds.LAST_MODIFICATION_DATE, new DirectLuceneBuilder(dictionaryService, ContentModel.PROP_MODIFIED)); + registerPropertyLuceneBuilder(PropertyIds.CHANGE_TOKEN, new FixedValueLuceneBuilder(null)); + registerPropertyLuceneBuilder(PropertyIds.NAME, new DirectLuceneBuilder(dictionaryService, ContentModel.PROP_NAME)); + registerPropertyLuceneBuilder(PropertyIds.DESCRIPTION, new DirectLuceneBuilder(dictionaryService, ContentModel.PROP_DESCRIPTION)); + registerPropertyLuceneBuilder(PropertyIds.IS_IMMUTABLE, new NotSupportedLuceneBuilder()); + registerPropertyLuceneBuilder(PropertyIds.IS_LATEST_VERSION, new NotSupportedLuceneBuilder()); + registerPropertyLuceneBuilder(PropertyIds.IS_MAJOR_VERSION, new NotSupportedLuceneBuilder()); + registerPropertyLuceneBuilder(PropertyIds.IS_LATEST_MAJOR_VERSION, new NotSupportedLuceneBuilder()); + registerPropertyLuceneBuilder(PropertyIds.VERSION_LABEL, new NotSupportedLuceneBuilder()); + registerPropertyLuceneBuilder(PropertyIds.VERSION_SERIES_ID, new NotSupportedLuceneBuilder()); + registerPropertyLuceneBuilder(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT, new NotSupportedLuceneBuilder()); + registerPropertyLuceneBuilder(PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, new NotSupportedLuceneBuilder()); + registerPropertyLuceneBuilder(PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, new NotSupportedLuceneBuilder()); + registerPropertyLuceneBuilder(PropertyIds.CHECKIN_COMMENT, new NotSupportedLuceneBuilder()); + registerPropertyLuceneBuilder(PropertyIds.CONTENT_STREAM_LENGTH, new ContentStreamLengthLuceneBuilder(dictionaryService)); + registerPropertyLuceneBuilder(PropertyIds.CONTENT_STREAM_MIME_TYPE, new ContentStreamMimetypeLuceneBuilder(dictionaryService)); + registerPropertyLuceneBuilder(PropertyIds.CONTENT_STREAM_ID, new NotSupportedLuceneBuilder()); + registerPropertyLuceneBuilder(PropertyIds.CONTENT_STREAM_FILE_NAME, new DirectLuceneBuilder(dictionaryService, ContentModel.PROP_NAME)); + registerPropertyLuceneBuilder(PropertyIds.PARENT_ID, new ParentLuceneBuilder(dictionaryService)); + registerPropertyLuceneBuilder(PropertyIds.PATH, new NotSupportedLuceneBuilder()); + registerPropertyLuceneBuilder(PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS, new NotSupportedLuceneBuilder()); + registerPropertyLuceneBuilder(PropertyIds.SOURCE_ID, new NotSupportedLuceneBuilder()); + registerPropertyLuceneBuilder(PropertyIds.TARGET_ID, new NotSupportedLuceneBuilder()); + + registerPropertyLuceneBuilder("alfcmis:nodeRef", new NotSupportedLuceneBuilder()); + } + + @Override + public CMISPropertyLuceneBuilder getPropertyLuceneBuilder(String propertyId) + { + return luceneBuilders.get(propertyId); + } + + @Override + public CMISPropertyLuceneBuilder createDirectPropertyLuceneBuilder(QName propertyName) + { + return new DirectLuceneBuilder(dictionaryService, propertyName); + } + + /** + * Register pre-defined Property Accessor + * + * @param name String + * @param luceneBuilder CMISPropertyLuceneBuilder + */ + private void registerPropertyLuceneBuilder(String name, CMISPropertyLuceneBuilder luceneBuilder) + { + luceneBuilders.put(name, luceneBuilder); + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/search/CMISFTSQueryParser.java b/data-model/src/main/java/org/alfresco/opencmis/search/CMISFTSQueryParser.java new file mode 100644 index 0000000000..9751abe710 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/search/CMISFTSQueryParser.java @@ -0,0 +1,424 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.search; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.search.adaptor.lucene.AnalysisMode; +import org.alfresco.repo.search.impl.parsers.CMIS_FTSLexer; +import org.alfresco.repo.search.impl.parsers.CMIS_FTSParser; +import org.alfresco.repo.search.impl.parsers.FTSQueryException; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.Column; +import org.alfresco.repo.search.impl.querymodel.Constraint; +import org.alfresco.repo.search.impl.querymodel.Constraint.Occur; +import org.alfresco.repo.search.impl.querymodel.Function; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.LiteralArgument; +import org.alfresco.repo.search.impl.querymodel.QueryModelFactory; +import org.alfresco.repo.search.impl.querymodel.QueryOptions.Connective; +import org.alfresco.repo.search.impl.querymodel.Selector; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSPhrase; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSTerm; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.antlr.runtime.ANTLRStringStream; +import org.antlr.runtime.CharStream; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +public class CMISFTSQueryParser +{ + @SuppressWarnings("unused") + static public Constraint buildFTS(String ftsExpression, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, Selector selector, + Map columnMap, String defaultField) + { + // TODO: Decode sql escape for '' should do in CMIS layer + + // parse templates to trees ... + + CMIS_FTSParser parser = null; + try + { + CharStream cs = new ANTLRStringStream(ftsExpression); + CMIS_FTSLexer lexer = new CMIS_FTSLexer(cs); + CommonTokenStream tokens = new CommonTokenStream(lexer); + parser = new CMIS_FTSParser(tokens); + CommonTree ftsNode = (CommonTree) parser.cmisFtsQuery().getTree(); + return buildFTSConnective(ftsNode, factory, functionEvaluationContext, selector, columnMap, defaultField); + } + catch (RecognitionException e) + { + if (parser != null) + { + String[] tokenNames = parser.getTokenNames(); + String hdr = parser.getErrorHeader(e); + String msg = parser.getErrorMessage(e, tokenNames); + throw new FTSQueryException(hdr + "\n" + msg, e); + } + return null; + } + + } + + static private Constraint buildFTSConnective(CommonTree node, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap, String defaultField) + { + Connective connective; + switch (node.getType()) + { + case CMIS_FTSParser.DISJUNCTION: + connective = Connective.OR; + break; + case CMIS_FTSParser.CONJUNCTION: + connective = Connective.AND; + break; + default: + throw new FTSQueryException("Invalid connective ..." + node.getText()); + } + + List constraints = new ArrayList(node.getChildCount()); + CommonTree testNode; + for (int i = 0; i < node.getChildCount(); i++) + { + CommonTree subNode = (CommonTree) node.getChild(i); + Constraint constraint; + switch (subNode.getType()) + { + case CMIS_FTSParser.DISJUNCTION: + case CMIS_FTSParser.CONJUNCTION: + constraint = buildFTSConnective(subNode, factory, functionEvaluationContext, selector, columnMap, defaultField); + break; + case CMIS_FTSParser.DEFAULT: + testNode = (CommonTree) subNode.getChild(0); + constraint = buildFTSTest(testNode, factory, functionEvaluationContext, selector, columnMap, defaultField); + constraint.setOccur(Occur.DEFAULT); + break; + case CMIS_FTSParser.EXCLUDE: + testNode = (CommonTree) subNode.getChild(0); + constraint = buildFTSTest(testNode, factory, functionEvaluationContext, selector, columnMap, defaultField); + constraint.setOccur(Occur.EXCLUDE); + break; + + default: + throw new FTSQueryException("Unsupported FTS option " + subNode.getText()); + } + constraints.add(constraint); + } + if (constraints.size() == 1) + { + return constraints.get(0); + } + else + { + if (connective == Connective.OR) + { + return factory.createDisjunction(constraints); + } + else + { + return factory.createConjunction(constraints); + } + } + } + + static private Constraint buildFTSTest(CommonTree argNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap, String defaultField) + { + CommonTree testNode = argNode; + switch (testNode.getType()) + { + case CMIS_FTSParser.DISJUNCTION: + case CMIS_FTSParser.CONJUNCTION: + return buildFTSConnective(testNode, factory, functionEvaluationContext, selector, columnMap, defaultField); + case CMIS_FTSParser.TERM: + return buildTerm(testNode, factory, functionEvaluationContext, selector, columnMap); + case CMIS_FTSParser.PHRASE: + return buildPhrase(testNode, factory, functionEvaluationContext, selector, columnMap); + default: + throw new FTSQueryException("Unsupported FTS option " + testNode.getText()); + } + } + + static private Constraint buildPhrase(CommonTree testNode, QueryModelFactory factory, + FunctionEvaluationContext functionEvaluationContext, Selector selector, Map columnMap) + { + String functionName = FTSPhrase.NAME; + Function function = factory.getFunction(functionName); + Map functionArguments = new LinkedHashMap(); + LiteralArgument larg = factory.createLiteralArgument(FTSPhrase.ARG_PHRASE, DataTypeDefinition.TEXT, getText(testNode.getChild(0))); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSPhrase.ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, AnalysisMode.DEFAULT); + functionArguments.put(larg.getName(), larg); + return factory.createFunctionalConstraint(function, functionArguments); + } + + static private Constraint buildTerm(CommonTree testNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap) + { + String functionName = FTSTerm.NAME; + Function function = factory.getFunction(functionName); + Map functionArguments = new LinkedHashMap(); + LiteralArgument larg = factory.createLiteralArgument(FTSTerm.ARG_TERM, DataTypeDefinition.TEXT, getText(testNode.getChild(0))); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSTerm.ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, AnalysisMode.DEFAULT); + functionArguments.put(larg.getName(), larg); + return factory.createFunctionalConstraint(function, functionArguments); + } + + + static class DisjunctionToken implements Token + { + + public int getChannel() + { + return 0; + } + + public int getCharPositionInLine() + { + return 0; + } + + public CharStream getInputStream() + { + return null; + } + + public int getLine() + { + return 0; + } + + public String getText() + { + return null; + } + + public int getTokenIndex() + { + return 0; + } + + public int getType() + { + return CMIS_FTSParser.DISJUNCTION; + } + + public void setChannel(int arg0) + { + + + } + + public void setCharPositionInLine(int arg0) + { + + + } + + public void setInputStream(CharStream arg0) + { + + } + + public void setLine(int arg0) + { + + + } + + public void setText(String arg0) + { + + + } + + public void setTokenIndex(int arg0) + { + + } + + public void setType(int arg0) + { + + } + + } + + static class DefaultToken implements Token + { + + public int getChannel() + { + + return 0; + } + + public int getCharPositionInLine() + { + return 0; + } + + public CharStream getInputStream() + { + return null; + } + + public int getLine() + { + return 0; + } + + public String getText() + { + return null; + } + + public int getTokenIndex() + { + return 0; + } + + public int getType() + { + return CMIS_FTSParser.DEFAULT; + } + + public void setChannel(int arg0) + { + + } + + public void setCharPositionInLine(int arg0) + { + + } + + public void setInputStream(CharStream arg0) + { + + } + + public void setLine(int arg0) + { + + } + + public void setText(String arg0) + { + + } + + public void setTokenIndex(int arg0) + { + + } + + public void setType(int arg0) + { + + } + + } + + static private String getText(Tree node) + { + String text = node.getText(); + int index; + switch (node.getType()) + { + case CMIS_FTSParser.FTSWORD: + index = text.indexOf('\\'); + if (index == -1) + { + return text; + } + else + { + return unescape(text); + } + case CMIS_FTSParser.FTSPHRASE: + String phrase = text.substring(1, text.length() - 1); + index = phrase.indexOf('\\'); + if (index == -1) + { + return phrase; + } + else + { + return unescape(phrase); + } + default: + return text; + } + } + + static private String unescape(String string) + { + StringBuilder builder = new StringBuilder(string.length()); + boolean lastWasEscape = false; + + for (int i = 0; i < string.length(); i++) + { + char c = string.charAt(i); + if (lastWasEscape) + { + if (c == 'u') + { + throw new UnsupportedOperationException(string); + } + else + { + builder.append(c); + } + lastWasEscape = false; + } + else + { + if (c == '\\') + { + lastWasEscape = true; + } + else + { + builder.append(c); + } + } + } + if (lastWasEscape) + { + throw new FTSQueryException("Escape character at end of string " + string); + } + + return builder.toString(); + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/search/CMISQueryOptions.java b/data-model/src/main/java/org/alfresco/opencmis/search/CMISQueryOptions.java new file mode 100644 index 0000000000..df639f9fff --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/search/CMISQueryOptions.java @@ -0,0 +1,203 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.search; + +import java.util.Locale; + +import org.alfresco.repo.search.impl.querymodel.QueryOptions; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.LimitBy; +import org.alfresco.service.cmr.search.QueryParameterDefinition; +import org.alfresco.service.cmr.search.SearchParameters; +import org.alfresco.service.cmr.search.SearchService; +import org.apache.chemistry.opencmis.commons.enums.CmisVersion; +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * The options for a CMIS query + * + * @author andyh + */ +public class CMISQueryOptions extends QueryOptions +{ + public enum CMISQueryMode + { + CMS_STRICT, CMS_WITH_ALFRESCO_EXTENSIONS; + } + + private CMISQueryMode queryMode = CMISQueryMode.CMS_STRICT; + private CmisVersion cmisVersion = CmisVersion.CMIS_1_1; + + public static CMISQueryOptions create(SearchParameters searchParameters) + { + String sql = searchParameters.getQuery(); + + CMISQueryOptions options = new CMISQueryOptions(sql, searchParameters.getStores().get(0)); + options.setIncludeInTransactionData(!searchParameters.excludeDataInTheCurrentTransaction()); + options.setDefaultFTSConnective(searchParameters.getDefaultOperator() == SearchParameters.Operator.OR ? Connective.OR : Connective.AND); + options.setDefaultFTSFieldConnective(searchParameters.getDefaultOperator() == SearchParameters.Operator.OR ? Connective.OR : Connective.AND); + options.setSkipCount(searchParameters.getSkipCount()); + options.setMaxPermissionChecks(searchParameters.getMaxPermissionChecks()); + options.setMaxPermissionCheckTimeMillis(searchParameters.getMaxPermissionCheckTimeMillis()); + if (searchParameters.getLimitBy() == LimitBy.FINAL_SIZE) + { + options.setMaxItems(searchParameters.getLimit()); + } + else + { + options.setMaxItems(searchParameters.getMaxItems()); + } + options.setMlAnalaysisMode(searchParameters.getMlAnalaysisMode()); + options.setLocales(searchParameters.getLocales()); + options.setStores(searchParameters.getStores()); + options.setUseInMemorySort(searchParameters.getUseInMemorySort()); + options.setMaxRawResultSetSizeForInMemorySort(searchParameters.getMaxRawResultSetSizeForInMemorySort()); + //options.setQuery(); Done on conbstruction + //options.setQueryMode(); Should set afterwards + options.setQueryParameterDefinitions(searchParameters.getQueryParameterDefinitions()); + options.setDefaultFieldName(searchParameters.getDefaultFieldName()); + options.setBulkFetchEnabled(searchParameters.isBulkFetchEnabled()); + options.setExcludeTenantFilter(searchParameters.getExcludeTenantFilter()); + options.setSinceTxId(searchParameters.getSinceTxId()); + for(String name : searchParameters.getQueryTemplates().keySet()) + { + String template = searchParameters.getQueryTemplates().get(name); + options.addQueryTemplate(name, template); + } + return options; + } + + /** + * Create a CMISQueryOptions instance with the default options other than + * the query and store ref. The query will be run using the locale returned + * by I18NUtil.getLocale() + * + * @param query + * - the query to run + * @param storeRef + * - the store against which to run the query + */ + public CMISQueryOptions(String query, StoreRef storeRef) + { + this(query, storeRef, I18NUtil.getLocale()); + } + + /** + * Create a CMISQueryOptions instance with the default options other than + * the query, store ref and locale. + * + * @param query + * - the query to run + * @param storeRef + * - the store against which to run the query + */ + public CMISQueryOptions(String query, StoreRef storeRef, Locale locale) + { + super(query, storeRef, locale); + } + + public CmisVersion getCmisVersion() + { + return cmisVersion; + } + + public void setCmisVersion(CmisVersion cmisVersion) + { + this.cmisVersion = cmisVersion; + } + + /** + * Get the query mode. + * + * @return the queryMode + */ + public CMISQueryMode getQueryMode() + { + return queryMode; + } + + /** + * Set the query mode. + * + * @param queryMode + * the queryMode to set + */ + public void setQueryMode(CMISQueryMode queryMode) + { + this.queryMode = queryMode; + } + + /** + * @return SearchParameters + */ + public SearchParameters getAsSearchParmeters() + { + SearchParameters searchParameters = new SearchParameters(); + searchParameters.setDefaultFieldName(this.getDefaultFieldName()); + searchParameters.setDefaultFTSFieldConnective(this.getDefaultFTSFieldConnective() == Connective.OR ? SearchParameters.Operator.OR : SearchParameters.Operator.AND); + searchParameters.setDefaultFTSOperator(this.getDefaultFTSConnective() == Connective.OR ? SearchParameters.Operator.OR : SearchParameters.Operator.AND); + searchParameters.setDefaultOperator(this.getDefaultFTSConnective() == Connective.OR ? SearchParameters.Operator.OR : SearchParameters.Operator.AND); + searchParameters.setLanguage(SearchService.LANGUAGE_CMIS_ALFRESCO); + if(this.getMaxItems() > 0) + { + searchParameters.setLimit(this.getMaxItems()); + searchParameters.setLimitBy(LimitBy.FINAL_SIZE); + searchParameters.setMaxItems(this.getMaxItems()); + } + searchParameters.setMaxPermissionChecks(this.getMaxPermissionChecks()); + searchParameters.setMaxPermissionCheckTimeMillis(this.getMaxPermissionCheckTimeMillis()); + searchParameters.setMlAnalaysisMode(this.getMlAnalaysisMode()); + //searchParameters.setNamespace() TODO: Fix + //searchParameters.setPermissionEvaluation() + searchParameters.setQuery(this.getQuery()); + searchParameters.setSkipCount(this.getSkipCount()); + //searchParameters.addAllAttribute() + for(Locale locale : this.getLocales()) + { + searchParameters.addLocale(locale); + } + for(QueryParameterDefinition queryParameterDefinition: this.getQueryParameterDefinitions()) + { + searchParameters.addQueryParameterDefinition(queryParameterDefinition); + } + //searchParameters.addQueryTemplate(name, template) + //searchParameters.addSort() + for(StoreRef storeRef : this.getStores()) + { + searchParameters.addStore(storeRef); + } + //searchParameters.addTextAttribute() + searchParameters.setBulkFetchEnabled(isBulkFetchEnabled()); + searchParameters.setQueryConsistency(this.getQueryConsistency()); + searchParameters.setSinceTxId(getSinceTxId()); + for(String name : getQueryTemplates().keySet()) + { + String template = getQueryTemplates().get(name); + searchParameters.addQueryTemplate(name, template); + } + return searchParameters; + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/search/CMISQueryParser.java b/data-model/src/main/java/org/alfresco/opencmis/search/CMISQueryParser.java new file mode 100644 index 0000000000..929854f4bd --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/search/CMISQueryParser.java @@ -0,0 +1,1728 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.search; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import org.alfresco.opencmis.dictionary.CMISDictionaryService; +import org.alfresco.opencmis.dictionary.PropertyDefinitionWrapper; +import org.alfresco.opencmis.dictionary.TypeDefinitionWrapper; +import org.alfresco.opencmis.search.CMISQueryOptions.CMISQueryMode; +import org.alfresco.repo.search.impl.parsers.CMISLexer; +import org.alfresco.repo.search.impl.parsers.CMISParser; +import org.alfresco.repo.search.impl.parsers.FTSParser; +import org.alfresco.repo.search.impl.parsers.FTSQueryException; +import org.alfresco.repo.search.impl.parsers.FTSQueryParser; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.Column; +import org.alfresco.repo.search.impl.querymodel.Constraint; +import org.alfresco.repo.search.impl.querymodel.Constraint.Occur; +import org.alfresco.repo.search.impl.querymodel.Function; +import org.alfresco.repo.search.impl.querymodel.FunctionArgument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.JoinType; +import org.alfresco.repo.search.impl.querymodel.ListArgument; +import org.alfresco.repo.search.impl.querymodel.LiteralArgument; +import org.alfresco.repo.search.impl.querymodel.Order; +import org.alfresco.repo.search.impl.querymodel.Ordering; +import org.alfresco.repo.search.impl.querymodel.ParameterArgument; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.Query; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.QueryModelFactory; +import org.alfresco.repo.search.impl.querymodel.QueryOptions.Connective; +import org.alfresco.repo.search.impl.querymodel.Selector; +import org.alfresco.repo.search.impl.querymodel.SelectorArgument; +import org.alfresco.repo.search.impl.querymodel.Source; +import org.alfresco.repo.search.impl.querymodel.impl.BaseComparison; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Child; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Descendant; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Equals; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Exists; +import org.alfresco.repo.search.impl.querymodel.impl.functions.GreaterThan; +import org.alfresco.repo.search.impl.querymodel.impl.functions.GreaterThanOrEquals; +import org.alfresco.repo.search.impl.querymodel.impl.functions.In; +import org.alfresco.repo.search.impl.querymodel.impl.functions.LessThan; +import org.alfresco.repo.search.impl.querymodel.impl.functions.LessThanOrEquals; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Like; +import org.alfresco.repo.search.impl.querymodel.impl.functions.NotEquals; +import org.alfresco.repo.search.impl.querymodel.impl.functions.PropertyAccessor; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Score; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.CachingDateFormat; +import org.antlr.runtime.ANTLRStringStream; +import org.antlr.runtime.CharStream; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.tree.CommonTree; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.chemistry.opencmis.commons.enums.CapabilityJoin; +import org.apache.chemistry.opencmis.commons.enums.PropertyType; +import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; + +/** + * @author andyh + */ +public class CMISQueryParser +{ + private enum EscapeMode + { + LITERAL, LIKE, CONTAINS; + } + + private CMISQueryOptions options; + + private CMISDictionaryService cmisDictionaryService; + + private CapabilityJoin joinSupport; + + private BaseTypeId[] validScopes; + + private boolean hasScore = false; + + private boolean hasContains = false; + + public CMISQueryParser(CMISQueryOptions options, CMISDictionaryService cmisDictionaryService, + CapabilityJoin joinSupport) + { + this.options = options; + this.cmisDictionaryService = cmisDictionaryService; + this.joinSupport = joinSupport; + this.validScopes = (options.getQueryMode() == CMISQueryMode.CMS_STRICT) ? CmisFunctionEvaluationContext.STRICT_SCOPES + : CmisFunctionEvaluationContext.ALFRESCO_SCOPES; + } + + @SuppressWarnings("unused") + public Query parse(QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext) + { + + CMISParser parser = null; + try + { + CharStream cs = new ANTLRStringStream(options.getQuery()); + CMISLexer lexer = new CMISLexer(cs); + CommonTokenStream tokens = new CommonTokenStream(lexer); + parser = new CMISParser(tokens); + parser.setStrict(options.getQueryMode() == CMISQueryMode.CMS_STRICT); + CommonTree queryNode = (CommonTree) parser.query().getTree(); + + CommonTree sourceNode = (CommonTree) queryNode.getFirstChildWithType(CMISParser.SOURCE); + Source source = buildSource(sourceNode, joinSupport, factory, JoinType.NONE); + Map selectors = source.getSelectors(); + ArrayList columns = buildColumns(queryNode, factory, selectors, options.getQuery()); + + HashMap columnMap = new HashMap(); + for (Column column : columns) + { + if (columnMap.containsKey(column.getAlias())) + { + throw new CmisInvalidArgumentException("Duplicate column alias for " + column.getAlias()); + } else + { + columnMap.put(column.getAlias(), column); + } + } + + ArrayList orderings = buildOrderings(queryNode, factory, selectors, columns); + + Constraint constraint = null; + CommonTree orNode = (CommonTree) queryNode.getFirstChildWithType(CMISParser.DISJUNCTION); + if (orNode != null) + { + constraint = buildDisjunction(orNode, factory, functionEvaluationContext, selectors, columnMap); + } + + Query query = factory.createQuery(columns, source, constraint, orderings); + + // TODO: validate query and use of ID, function arguments matching + // up etc + + if (options.getQueryMode() == CMISQueryMode.CMS_STRICT) + { + if (hasScore && !hasContains) + { + throw new CmisInvalidArgumentException("Function SCORE() used without matching CONTAINS() function"); + } + } + + return query; + } catch (RecognitionException e) + { + if (parser != null) + { + String[] tokenNames = parser.getTokenNames(); + String hdr = parser.getErrorHeader(e); + String msg = parser.getErrorMessage(e, tokenNames); + throw new CmisInvalidArgumentException(hdr + "\n" + msg, e); + } + } + throw new CmisInvalidArgumentException("Failed to parse"); + } + + /** + * @param orNode CommonTree + * @param factory QueryModelFactory + * @param functionEvaluationContext FunctionEvaluationContext + * @param selectors Map + * @param columnMap HashMap + * @return Constraint + */ + private Constraint buildDisjunction(CommonTree orNode, QueryModelFactory factory, + FunctionEvaluationContext functionEvaluationContext, Map selectors, + HashMap columnMap) + { + List constraints = new ArrayList(orNode.getChildCount()); + for (int i = 0; i < orNode.getChildCount(); i++) + { + CommonTree andNode = (CommonTree) orNode.getChild(i); + Constraint constraint = buildConjunction(andNode, factory, functionEvaluationContext, selectors, columnMap); + constraints.add(constraint); + } + if (constraints.size() == 1) + { + return constraints.get(0); + } else + { + return factory.createDisjunction(constraints); + } + } + + /** + * @param andNode CommonTree + * @param factory QueryModelFactory + * @param functionEvaluationContext FunctionEvaluationContext + * @param selectors Map + * @param columnMap HashMap + * @return Constraint + */ + private Constraint buildConjunction(CommonTree andNode, QueryModelFactory factory, + FunctionEvaluationContext functionEvaluationContext, Map selectors, + HashMap columnMap) + { + List constraints = new ArrayList(andNode.getChildCount()); + for (int i = 0; i < andNode.getChildCount(); i++) + { + CommonTree notNode = (CommonTree) andNode.getChild(i); + Constraint constraint = buildNegation(notNode, factory, functionEvaluationContext, selectors, columnMap); + constraints.add(constraint); + } + if (constraints.size() == 1 && constraints.get(0).getOccur() != Occur.EXCLUDE) + { + return constraints.get(0); + } else + { + return factory.createConjunction(constraints); + } + } + + /** + * @param notNode CommonTree + * @param factory QueryModelFactory + * @param functionEvaluationContext FunctionEvaluationContext + * @param selectors Map + * @param columnMap HashMap + * @return Constraint + */ + private Constraint buildNegation(CommonTree notNode, QueryModelFactory factory, + FunctionEvaluationContext functionEvaluationContext, Map selectors, + HashMap columnMap) + { + if (notNode.getType() == CMISParser.NEGATION) + { + Constraint constraint = buildTest((CommonTree) notNode.getChild(0), factory, functionEvaluationContext, + selectors, columnMap); + constraint.setOccur(Occur.EXCLUDE); + return constraint; + } else + { + return buildTest(notNode, factory, functionEvaluationContext, selectors, columnMap); + } + } + + /** + * @param testNode CommonTree + * @param factory QueryModelFactory + * @param functionEvaluationContext FunctionEvaluationContext + * @param selectors Map + * @param columnMap HashMap + * @return Constraint + */ + private Constraint buildTest(CommonTree testNode, QueryModelFactory factory, + FunctionEvaluationContext functionEvaluationContext, Map selectors, + HashMap columnMap) + { + if (testNode.getType() == CMISParser.DISJUNCTION) + { + return buildDisjunction(testNode, factory, functionEvaluationContext, selectors, columnMap); + } else + { + return buildPredicate(testNode, factory, functionEvaluationContext, selectors, columnMap); + } + } + + /** + * @param predicateNode CommonTree + * @param factory QueryModelFactory + * @param functionEvaluationContext FunctionEvaluationContext + * @param selectors Map + * @param columnMap HashMap + * @return Constraint + */ + private Constraint buildPredicate(CommonTree predicateNode, QueryModelFactory factory, + FunctionEvaluationContext functionEvaluationContext, Map selectors, + Map columnMap) + { + String functionName; + Function function; + CommonTree argNode; + Map functionArguments; + Argument arg; + switch (predicateNode.getType()) + { + case CMISParser.PRED_CHILD: + functionName = Child.NAME; + function = factory.getFunction(functionName); + functionArguments = new LinkedHashMap(); + argNode = (CommonTree) predicateNode.getChild(0); + arg = getFunctionArgument(argNode, function.getArgumentDefinition(Child.ARG_PARENT), factory, selectors, + columnMap, false); + functionArguments.put(arg.getName(), arg); + if (predicateNode.getChildCount() > 1) + { + argNode = (CommonTree) predicateNode.getChild(1); + arg = getFunctionArgument(argNode, function.getArgumentDefinition(Child.ARG_SELECTOR), factory, + selectors, columnMap, false); + if (!arg.isQueryable()) + { + throw new CmisInvalidArgumentException("The property is not queryable: " + argNode.getText()); + } + functionArguments.put(arg.getName(), arg); + } + return factory.createFunctionalConstraint(function, functionArguments); + case CMISParser.PRED_COMPARISON: + + switch (predicateNode.getChild(2).getType()) + { + case CMISParser.EQUALS: + functionName = Equals.NAME; + function = factory.getFunction(functionName); + break; + case CMISParser.NOTEQUALS: + functionName = NotEquals.NAME; + function = factory.getFunction(functionName); + break; + case CMISParser.GREATERTHAN: + functionName = GreaterThan.NAME; + function = factory.getFunction(functionName); + break; + case CMISParser.GREATERTHANOREQUALS: + functionName = GreaterThanOrEquals.NAME; + function = factory.getFunction(functionName); + break; + case CMISParser.LESSTHAN: + functionName = LessThan.NAME; + function = factory.getFunction(functionName); + break; + case CMISParser.LESSTHANOREQUALS: + functionName = LessThanOrEquals.NAME; + function = factory.getFunction(functionName); + break; + default: + throw new CmisInvalidArgumentException("Unknown comparison function " + + predicateNode.getChild(2).getText()); + } + functionArguments = new LinkedHashMap(); + argNode = (CommonTree) predicateNode.getChild(0); + arg = getFunctionArgument(argNode, function.getArgumentDefinition(BaseComparison.ARG_MODE), factory, + selectors, columnMap, false); + functionArguments.put(arg.getName(), arg); + argNode = (CommonTree) predicateNode.getChild(1); + arg = getFunctionArgument(argNode, function.getArgumentDefinition(BaseComparison.ARG_LHS), factory, + selectors, columnMap, false); + functionArguments.put(arg.getName(), arg); + argNode = (CommonTree) predicateNode.getChild(3); + arg = getFunctionArgument(argNode, function.getArgumentDefinition(BaseComparison.ARG_RHS), factory, + selectors, columnMap, false); + functionArguments.put(arg.getName(), arg); + checkPredicateConditionsForComparisons(function, functionArguments, functionEvaluationContext, columnMap); + return factory.createFunctionalConstraint(function, functionArguments); + case CMISParser.PRED_DESCENDANT: + functionName = Descendant.NAME; + function = factory.getFunction(functionName); + argNode = (CommonTree) predicateNode.getChild(0); + functionArguments = new LinkedHashMap(); + arg = getFunctionArgument(argNode, function.getArgumentDefinition(Descendant.ARG_ANCESTOR), factory, + selectors, columnMap, false); + functionArguments.put(arg.getName(), arg); + if (predicateNode.getChildCount() > 1) + { + argNode = (CommonTree) predicateNode.getChild(1); + arg = getFunctionArgument(argNode, function.getArgumentDefinition(Descendant.ARG_SELECTOR), factory, + selectors, columnMap, false); + functionArguments.put(arg.getName(), arg); + } + return factory.createFunctionalConstraint(function, functionArguments); + case CMISParser.PRED_EXISTS: + functionName = Exists.NAME; + function = factory.getFunction(functionName); + argNode = (CommonTree) predicateNode.getChild(0); + functionArguments = new LinkedHashMap(); + arg = getFunctionArgument(argNode, function.getArgumentDefinition(Exists.ARG_PROPERTY), factory, selectors, + columnMap, false); + functionArguments.put(arg.getName(), arg); + arg = factory.createLiteralArgument(Exists.ARG_NOT, DataTypeDefinition.BOOLEAN, + (predicateNode.getChildCount() > 1)); + functionArguments.put(arg.getName(), arg); + // Applies to both single valued and multi-valued properties - no + // checks required + return factory.createFunctionalConstraint(function, functionArguments); + case CMISParser.PRED_FTS: + if (options.getQueryMode() == CMISQueryMode.CMS_STRICT) + { + if (hasContains) + { + throw new CmisInvalidArgumentException( + "Only one CONTAINS() function can be included in a single query statement."); + } + } + String ftsExpression = predicateNode.getChild(0).getText(); + ftsExpression = ftsExpression.substring(1, ftsExpression.length() - 1); + ftsExpression = unescape(ftsExpression, EscapeMode.CONTAINS); + Selector selector; + if (predicateNode.getChildCount() > 1) + { + String qualifier = predicateNode.getChild(1).getText(); + selector = selectors.get(qualifier); + if (selector == null) + { + throw new CmisInvalidArgumentException("No selector for " + qualifier); + } + } else + { + if (selectors.size() == 1) + { + selector = selectors.get(selectors.keySet().iterator().next()); + } else + { + throw new CmisInvalidArgumentException( + "A selector must be specified when there are two or more selectors"); + } + } + Connective defaultConnective; + Connective defaultFieldConnective; + if (options.getQueryMode() == CMISQueryMode.CMS_STRICT) + { + defaultConnective = Connective.AND; + defaultFieldConnective = Connective.AND; + } else + { + defaultConnective = options.getDefaultFTSConnective(); + defaultFieldConnective = options.getDefaultFTSFieldConnective(); + } + FTSParser.Mode mode; + if (options.getQueryMode() == CMISQueryMode.CMS_STRICT) + { + mode = FTSParser.Mode.CMIS; + } else + { + if (defaultConnective == Connective.AND) + { + mode = FTSParser.Mode.DEFAULT_CONJUNCTION; + } else + { + mode = FTSParser.Mode.DEFAULT_DISJUNCTION; + } + } + Constraint ftsConstraint; + if (options.getQueryMode() == CMISQueryMode.CMS_STRICT) + { + ftsConstraint = CMISFTSQueryParser.buildFTS(ftsExpression, factory, functionEvaluationContext, + selector, columnMap, options.getDefaultFieldName()); + } else + { + ftsConstraint = FTSQueryParser.buildFTS(ftsExpression, factory, functionEvaluationContext, selector, + columnMap, mode, defaultFieldConnective, options.getQueryTemplates(), options.getDefaultFieldName(), FTSQueryParser.RerankPhase.SINGLE_PASS); + } + ftsConstraint.setBoost(1000.0f); + hasContains = true; + return ftsConstraint; + case CMISParser.PRED_IN: + functionName = In.NAME; + function = factory.getFunction(functionName); + functionArguments = new LinkedHashMap(); + argNode = (CommonTree) predicateNode.getChild(0); + arg = getFunctionArgument(argNode, function.getArgumentDefinition(In.ARG_MODE), factory, selectors, + columnMap, false); + functionArguments.put(arg.getName(), arg); + argNode = (CommonTree) predicateNode.getChild(1); + arg = getFunctionArgument(argNode, function.getArgumentDefinition(In.ARG_PROPERTY), factory, selectors, + columnMap, false); + functionArguments.put(arg.getName(), arg); + argNode = (CommonTree) predicateNode.getChild(2); + arg = getFunctionArgument(argNode, function.getArgumentDefinition(In.ARG_LIST), factory, selectors, + columnMap, false); + functionArguments.put(arg.getName(), arg); + arg = factory.createLiteralArgument(In.ARG_NOT, DataTypeDefinition.BOOLEAN, + (predicateNode.getChildCount() > 3)); + functionArguments.put(arg.getName(), arg); + checkPredicateConditionsForIn(functionArguments, functionEvaluationContext, columnMap); + return factory.createFunctionalConstraint(function, functionArguments); + case CMISParser.PRED_LIKE: + functionName = Like.NAME; + function = factory.getFunction(functionName); + functionArguments = new LinkedHashMap(); + argNode = (CommonTree) predicateNode.getChild(0); + arg = getFunctionArgument(argNode, function.getArgumentDefinition(Like.ARG_PROPERTY), factory, selectors, + columnMap, false); + functionArguments.put(arg.getName(), arg); + argNode = (CommonTree) predicateNode.getChild(1); + arg = getFunctionArgument(argNode, function.getArgumentDefinition(Like.ARG_EXP), factory, selectors, + columnMap, true); + functionArguments.put(arg.getName(), arg); + arg = factory.createLiteralArgument(Like.ARG_NOT, DataTypeDefinition.BOOLEAN, + (predicateNode.getChildCount() > 2)); + functionArguments.put(arg.getName(), arg); + checkPredicateConditionsForLike(functionArguments, functionEvaluationContext, columnMap); + return factory.createFunctionalConstraint(function, functionArguments); + default: + return null; + } + } + + private void checkPredicateConditionsForIn(Map functionArguments, + FunctionEvaluationContext functionEvaluationContext, Map columnMap) + { + if (options.getQueryMode() == CMISQueryMode.CMS_STRICT) + { + PropertyArgument propertyArgument = (PropertyArgument) functionArguments.get(In.ARG_PROPERTY); + LiteralArgument modeArgument = (LiteralArgument) functionArguments.get(In.ARG_MODE); + String modeString = DefaultTypeConverter.INSTANCE.convert(String.class, + modeArgument.getValue(functionEvaluationContext)); + PredicateMode mode = PredicateMode.valueOf(modeString); + String propertyName = propertyArgument.getPropertyName(); + + Column column = columnMap.get(propertyName); + if (column != null) + { + // check for function type + if (column.getFunction().getName().equals(PropertyAccessor.NAME)) + { + PropertyArgument arg = (PropertyArgument) column.getFunctionArguments().get( + PropertyAccessor.ARG_PROPERTY); + propertyName = arg.getPropertyName(); + } else + { + throw new CmisInvalidArgumentException("Complex column reference not supoprted in LIKE " + + propertyName); + } + } + + boolean isMultiValued = functionEvaluationContext.isMultiValued(propertyName); + + switch (mode) + { + case ANY: + if (isMultiValued) + { + break; + } else + { + throw new QueryModelException("Predicate mode " + PredicateMode.ANY + + " is not supported for IN and single valued properties"); + } + case SINGLE_VALUED_PROPERTY: + if (isMultiValued) + { + throw new QueryModelException("Predicate mode " + PredicateMode.SINGLE_VALUED_PROPERTY + + " is not supported for IN and multi-valued properties"); + } else + { + break; + } + default: + throw new QueryModelException("Unsupported predicate mode " + mode); + } + + PropertyDefinitionWrapper propDef = cmisDictionaryService.findPropertyByQueryName(propertyName); + if (propDef.getPropertyDefinition().getPropertyType() == PropertyType.BOOLEAN) + { + throw new QueryModelException("In is not supported for properties of type Boolean"); + } + } + + } + + private void checkPredicateConditionsForComparisons(Function function, Map functionArguments, + FunctionEvaluationContext functionEvaluationContext, Map columnMap) + { + if (options.getQueryMode() == CMISQueryMode.CMS_STRICT) + { + ((BaseComparison) function).setPropertyAndStaticArguments(functionArguments); + String propertyName = ((BaseComparison) function).getPropertyName(); + LiteralArgument modeArgument = (LiteralArgument) functionArguments.get(BaseComparison.ARG_MODE); + String modeString = DefaultTypeConverter.INSTANCE.convert(String.class, + modeArgument.getValue(functionEvaluationContext)); + PredicateMode mode = PredicateMode.valueOf(modeString); + + Column column = columnMap.get(propertyName); + if (column != null) + { + // check for function type + if (column.getFunction().getName().equals(PropertyAccessor.NAME)) + { + PropertyArgument arg = (PropertyArgument) column.getFunctionArguments().get( + PropertyAccessor.ARG_PROPERTY); + propertyName = arg.getPropertyName(); + } else + { + throw new CmisInvalidArgumentException("Complex column reference not supoprted in LIKE " + + propertyName); + } + } + + boolean isMultiValued = functionEvaluationContext.isMultiValued(propertyName); + + switch (mode) + { + case ANY: + if (isMultiValued) + { + if (function.getName().equals(Equals.NAME)) + { + break; + } else + { + throw new QueryModelException("Predicate mode " + PredicateMode.ANY + " is only supported for " + + Equals.NAME + " (and multi-valued properties)."); + } + } else + { + throw new QueryModelException("Predicate mode " + PredicateMode.ANY + " is not supported for " + + function.getName() + " and single valued properties"); + } + case SINGLE_VALUED_PROPERTY: + if (isMultiValued) + { + throw new QueryModelException("Predicate mode " + PredicateMode.SINGLE_VALUED_PROPERTY + + " is not supported for " + function.getName() + " and multi-valued properties"); + } else + { + break; + } + default: + throw new QueryModelException("Unsupported predicate mode " + mode); + } + + // limit support for ID and Boolean + + PropertyDefinitionWrapper propDef = cmisDictionaryService.findPropertyByQueryName(propertyName); + if (propDef.getPropertyDefinition().getPropertyType() == PropertyType.ID) + { + if (function.getName().equals(Equals.NAME) || function.getName().equals(NotEquals.NAME)) + { + return; + } else + { + throw new QueryModelException("Comparison " + function.getName() + + " is not supported for properties of type ID"); + } + } else if (propDef.getPropertyDefinition().getPropertyType() == PropertyType.BOOLEAN) + { + if (function.getName().equals(Equals.NAME)) + { + return; + } else + { + throw new QueryModelException("Comparison " + function.getName() + + " is not supported for properties of type Boolean"); + } + } + } + + } + + private void checkPredicateConditionsForLike(Map functionArguments, + FunctionEvaluationContext functionEvaluationContext, Map columnMap) + { + if (options.getQueryMode() == CMISQueryMode.CMS_STRICT) + { + PropertyArgument propertyArgument = (PropertyArgument) functionArguments.get(Like.ARG_PROPERTY); + + boolean isMultiValued = functionEvaluationContext.isMultiValued(propertyArgument.getPropertyName()); + + if (isMultiValued) + { + throw new QueryModelException("Like is not supported for multi-valued properties"); + } + + String cmisPropertyName = propertyArgument.getPropertyName(); + + Column column = columnMap.get(cmisPropertyName); + if (column != null) + { + // check for function type + if (column.getFunction().getName().equals(PropertyAccessor.NAME)) + { + PropertyArgument arg = (PropertyArgument) column.getFunctionArguments().get( + PropertyAccessor.ARG_PROPERTY); + cmisPropertyName = arg.getPropertyName(); + } else + { + throw new CmisInvalidArgumentException("Complex column reference not supoprted in LIKE " + + cmisPropertyName); + } + } + + PropertyDefinitionWrapper propDef = cmisDictionaryService.findPropertyByQueryName(cmisPropertyName); + if (propDef.getPropertyDefinition().getPropertyType() != PropertyType.STRING) + { + throw new CmisInvalidArgumentException("LIKE is only supported against String types" + cmisPropertyName); + } + } + } + + /** + * @param queryNode CommonTree + * @param factory QueryModelFactory + * @param selectors Map selectors + * @param columns List + * @return ArrayList + */ + private ArrayList buildOrderings(CommonTree queryNode, QueryModelFactory factory, + Map selectors, List columns) + { + ArrayList orderings = new ArrayList(); + CommonTree orderNode = (CommonTree) queryNode.getFirstChildWithType(CMISParser.ORDER); + if (orderNode != null) + { + for (int i = 0; i < orderNode.getChildCount(); i++) + { + CommonTree current = (CommonTree) orderNode.getChild(i); + + CommonTree columnRefNode = (CommonTree) current.getFirstChildWithType(CMISParser.COLUMN_REF); + if (columnRefNode != null) + { + String columnName = columnRefNode.getChild(0).getText(); + String qualifier = ""; + if (columnRefNode.getChildCount() > 1) + { + qualifier = columnRefNode.getChild(1).getText(); + } + + Order order = Order.ASCENDING; + + if (current.getChild(1).getType() == CMISParser.DESC) + { + order = Order.DESCENDING; + } + + Column orderColumn = null; + + if (qualifier.length() == 0) + { + Column match = null; + for (Column column : columns) + { + if (column.getAlias().equals(columnName)) + { + match = column; + break; + } + if (column.getFunction().getName().equals(PropertyAccessor.NAME)) + { + PropertyArgument arg = (PropertyArgument) column.getFunctionArguments().get( + PropertyAccessor.ARG_PROPERTY); + String propertyName = arg.getPropertyName(); + if (propertyName.equals(columnName)) + { + match = column; + break; + } + } + } + // in strict mode the ordered column must be selected + if ((options.getQueryMode() == CMISQueryMode.CMS_STRICT) && (match == null)) + { + throw new CmisInvalidArgumentException("Ordered column is not selected: " + qualifier + "." + + columnName); + } + if (match == null) + { + + Selector selector = selectors.get(qualifier); + if (selector == null) + { + if ((qualifier.equals("")) && (selectors.size() == 1)) + { + selector = selectors.get(selectors.keySet().iterator().next()); + } else + { + throw new CmisInvalidArgumentException("No selector for " + qualifier); + } + } + + TypeDefinitionWrapper typeDef = cmisDictionaryService.findTypeForClass(selector.getType(), validScopes); + if (typeDef == null) + { + throw new CmisInvalidArgumentException("Type unsupported in CMIS queries: " + + selector.getAlias()); + } + PropertyDefinitionWrapper propDef = cmisDictionaryService + .findPropertyByQueryName(columnName); + if (propDef == null) + { + throw new CmisInvalidArgumentException("Invalid column for " + + typeDef.getTypeDefinition(false).getQueryName() + "." + columnName); + } + + // Check column/property applies to selector/type + + if (typeDef.getPropertyById(propDef.getPropertyId()) == null) + { + throw new CmisInvalidArgumentException("Invalid column for " + + typeDef.getTypeDefinition(false).getQueryName() + "." + columnName); + } + + // check there is a matching selector + + if (options.getQueryMode() == CMISQueryMode.CMS_STRICT) + { + boolean found = false; + for (Column column : columns) + { + if (column.getFunction().getName().equals(PropertyAccessor.NAME)) + { + PropertyArgument pa = (PropertyArgument) column.getFunctionArguments().get( + PropertyAccessor.ARG_PROPERTY); + if (pa.getPropertyName().equals(propDef.getPropertyId())) + { + found = true; + break; + } + } + } + if (!found) + { + throw new CmisInvalidArgumentException("Ordered column is not selected: " + + qualifier + "." + columnName); + } + } + + Function function = factory.getFunction(PropertyAccessor.NAME); + Argument arg = factory.createPropertyArgument(PropertyAccessor.ARG_PROPERTY, propDef + .getPropertyDefinition().isQueryable(), propDef.getPropertyDefinition() + .isOrderable(), selector.getAlias(), propDef.getPropertyId()); + Map functionArguments = new LinkedHashMap(); + functionArguments.put(arg.getName(), arg); + + String alias = (selector.getAlias().length() > 0) ? selector.getAlias() + "." + + propDef.getPropertyId() : propDef.getPropertyId(); + + match = factory.createColumn(function, functionArguments, alias); + } + + orderColumn = match; + } else + { + Selector selector = selectors.get(qualifier); + if (selector == null) + { + if ((qualifier.equals("")) && (selectors.size() == 1)) + { + selector = selectors.get(selectors.keySet().iterator().next()); + } else + { + throw new CmisInvalidArgumentException("No selector for " + qualifier); + } + } + + TypeDefinitionWrapper typeDef = cmisDictionaryService.findTypeForClass(selector.getType(), validScopes); + if (typeDef == null) + { + throw new CmisInvalidArgumentException("Type unsupported in CMIS queries: " + + selector.getAlias()); + } + PropertyDefinitionWrapper propDef = cmisDictionaryService.findPropertyByQueryName(columnName); + if (propDef == null) + { + throw new CmisInvalidArgumentException("Invalid column for " + + typeDef.getTypeDefinition(false).getQueryName() + "." + columnName + + " selector alias " + selector.getAlias()); + } + + // check there is a matching selector + + if (options.getQueryMode() == CMISQueryMode.CMS_STRICT) + { + boolean found = false; + for (Column column : columns) + { + if (column.getFunction().getName().equals(PropertyAccessor.NAME)) + { + PropertyArgument pa = (PropertyArgument) column.getFunctionArguments().get( + PropertyAccessor.ARG_PROPERTY); + if (pa.getPropertyName().equals(propDef.getPropertyId())) + { + found = true; + break; + } + } + } + if (!found) + { + throw new CmisInvalidArgumentException("Ordered column is not selected: " + qualifier + + "." + columnName); + } + } + + Function function = factory.getFunction(PropertyAccessor.NAME); + Argument arg = factory.createPropertyArgument(PropertyAccessor.ARG_PROPERTY, propDef + .getPropertyDefinition().isQueryable(), propDef.getPropertyDefinition().isOrderable(), + selector.getAlias(), propDef.getPropertyId()); + Map functionArguments = new LinkedHashMap(); + functionArguments.put(arg.getName(), arg); + + String alias = (selector.getAlias().length() > 0) ? selector.getAlias() + "." + + propDef.getPropertyId() : propDef.getPropertyId(); + + orderColumn = factory.createColumn(function, functionArguments, alias); + } + + if (!orderColumn.isOrderable() || !orderColumn.isQueryable()) + { + throw new CmisInvalidArgumentException("Ordering is not support for " + orderColumn.getAlias()); + } + + Ordering ordering = factory.createOrdering(orderColumn, order); + orderings.add(ordering); + + } + } + } + return orderings; + } + + @SuppressWarnings("unchecked") + private ArrayList buildColumns(CommonTree queryNode, QueryModelFactory factory, + Map selectors, String query) + { + ArrayList columns = new ArrayList(); + CommonTree starNode = (CommonTree) queryNode.getFirstChildWithType(CMISParser.ALL_COLUMNS); + if (starNode != null) + { + for (Selector selector : selectors.values()) + { + TypeDefinitionWrapper typeDef = cmisDictionaryService.findTypeForClass(selector.getType(), validScopes); + if (typeDef == null) + { + throw new CmisInvalidArgumentException("Type unsupported in CMIS queries: " + selector.getAlias()); + } + Collection propDefs = typeDef.getProperties(); + for (PropertyDefinitionWrapper definition : propDefs) + { + Function function = factory.getFunction(PropertyAccessor.NAME); + Argument arg = factory.createPropertyArgument(PropertyAccessor.ARG_PROPERTY, definition + .getPropertyDefinition().isQueryable(), definition.getPropertyDefinition().isOrderable(), + selector.getAlias(), definition.getPropertyId()); + Map functionArguments = new LinkedHashMap(); + functionArguments.put(arg.getName(), arg); + String alias = (selector.getAlias().length() > 0) ? selector.getAlias() + "." + + definition.getPropertyId() : definition.getPropertyId(); + Column column = factory.createColumn(function, functionArguments, alias); + columns.add(column); + } + } + } + + CommonTree columnsNode = (CommonTree) queryNode.getFirstChildWithType(CMISParser.COLUMNS); + if (columnsNode != null) + { + for (CommonTree columnNode : (List) columnsNode.getChildren()) + { + if (columnNode.getType() == CMISParser.ALL_COLUMNS) + { + String qualifier = columnNode.getChild(0).getText(); + Selector selector = selectors.get(qualifier); + if (selector == null) + { + if ((qualifier.equals("")) && (selectors.size() == 1)) + { + selector = selectors.get(selectors.keySet().iterator().next()); + } else + { + throw new CmisInvalidArgumentException("No selector for " + qualifier + " in " + qualifier + + ".*"); + } + } + + TypeDefinitionWrapper typeDef = cmisDictionaryService.findTypeForClass(selector.getType(), + validScopes); + if (typeDef == null) + { + throw new CmisInvalidArgumentException("Type unsupported in CMIS queries: " + + selector.getAlias()); + } + Collection propDefs = typeDef.getProperties(); + for (PropertyDefinitionWrapper definition : propDefs) + { + Function function = factory.getFunction(PropertyAccessor.NAME); + Argument arg = factory.createPropertyArgument(PropertyAccessor.ARG_PROPERTY, definition + .getPropertyDefinition().isQueryable(), definition.getPropertyDefinition() + .isOrderable(), selector.getAlias(), definition.getPropertyId()); + Map functionArguments = new LinkedHashMap(); + functionArguments.put(arg.getName(), arg); + String alias = (selector.getAlias().length() > 0) ? selector.getAlias() + "." + + definition.getPropertyId() : definition.getPropertyId(); + Column column = factory.createColumn(function, functionArguments, alias); + columns.add(column); + } + } + + if (columnNode.getType() == CMISParser.COLUMN) + { + CommonTree columnRefNode = (CommonTree) columnNode.getFirstChildWithType(CMISParser.COLUMN_REF); + if (columnRefNode != null) + { + String columnName = columnRefNode.getChild(0).getText(); + String qualifier = ""; + if (columnRefNode.getChildCount() > 1) + { + qualifier = columnRefNode.getChild(1).getText(); + } + Selector selector = selectors.get(qualifier); + if (selector == null) + { + if ((qualifier.equals("")) && (selectors.size() == 1)) + { + selector = selectors.get(selectors.keySet().iterator().next()); + } else + { + throw new CmisInvalidArgumentException("No selector for " + qualifier); + } + } + + TypeDefinitionWrapper typeDef = cmisDictionaryService.findTypeForClass(selector.getType(), + validScopes); + if (typeDef == null) + { + throw new CmisInvalidArgumentException("Type unsupported in CMIS queries: " + + selector.getAlias()); + } + PropertyDefinitionWrapper propDef = cmisDictionaryService.findPropertyByQueryName(columnName); + if (propDef == null) + { + throw new CmisInvalidArgumentException("Invalid column for " + + typeDef.getTypeDefinition(false).getQueryName() + " " + columnName); + } + + // Check column/property applies to selector/type + + if (typeDef.getPropertyById(propDef.getPropertyId()) == null) + { + throw new CmisInvalidArgumentException("Invalid column for " + + typeDef.getTypeDefinition(false).getQueryName() + "." + columnName); + } + + Function function = factory.getFunction(PropertyAccessor.NAME); + Argument arg = factory.createPropertyArgument(PropertyAccessor.ARG_PROPERTY, propDef + .getPropertyDefinition().isQueryable(), propDef.getPropertyDefinition().isOrderable(), + selector.getAlias(), propDef.getPropertyId()); + Map functionArguments = new LinkedHashMap(); + functionArguments.put(arg.getName(), arg); + + String alias = (selector.getAlias().length() > 0) ? selector.getAlias() + "." + + propDef.getPropertyId() : propDef.getPropertyId(); + if (columnNode.getChildCount() > 1) + { + alias = columnNode.getChild(1).getText(); + } + + Column column = factory.createColumn(function, functionArguments, alias); + columns.add(column); + + } + + CommonTree functionNode = (CommonTree) columnNode.getFirstChildWithType(CMISParser.FUNCTION); + if (functionNode != null) + { + CommonTree functionNameNode = (CommonTree) functionNode.getChild(0); + Function function = factory.getFunction(functionNameNode.getText()); + if (function == null) + { + throw new CmisInvalidArgumentException("Unknown function: " + functionNameNode.getText()); + } + Collection definitions = function.getArgumentDefinitions().values(); + Map functionArguments = new LinkedHashMap(); + + int childIndex = 2; + for (ArgumentDefinition definition : definitions) + { + if (functionNode.getChildCount() > childIndex + 1) + { + CommonTree argNode = (CommonTree) functionNode.getChild(childIndex++); + Argument arg = getFunctionArgument(argNode, definition, factory, selectors, null, + function.getName().equals(Like.NAME)); + functionArguments.put(arg.getName(), arg); + } else + { + if (definition.isMandatory()) + { + // throw new + // CmisInvalidArgumentException("Insufficient + // aruments + // for function " + + // ((CommonTree) + // functionNode.getChild(0)).getText() ); + break; + } else + { + // ok + } + } + } + + CommonTree rparenNode = (CommonTree) functionNode.getChild(functionNode.getChildCount() - 1); + + int start = getStringPosition(query, functionNode.getLine(), + functionNode.getCharPositionInLine()); + int end = getStringPosition(query, rparenNode.getLine(), rparenNode.getCharPositionInLine()); + + if (function.getName().equals(Score.NAME)) + { + hasScore = true; + } + + String alias; + if (function.getName().equals(Score.NAME)) + { + alias = "SEARCH_SCORE"; + // check no args + if (functionNode.getChildCount() > 3) + { + throw new CmisInvalidArgumentException( + "The function SCORE() is not allowed any arguments"); + } + } else + { + alias = query.substring(start, end + 1); + } + if (columnNode.getChildCount() > 1) + { + alias = columnNode.getChild(1).getText(); + } + + Column column = factory.createColumn(function, functionArguments, alias); + columns.add(column); + } + } + } + } + + return columns; + } + + /** + * @param query String + * @param line int + * @param charPositionInLine int + * @return int + */ + private int getStringPosition(String query, int line, int charPositionInLine) + { + StringTokenizer tokenizer = new StringTokenizer(query, "\n\r\f"); + String[] lines = new String[tokenizer.countTokens()]; + int i = 0; + while (tokenizer.hasMoreElements()) + { + lines[i++] = tokenizer.nextToken(); + } + + int position = 0; + for (i = 0; i < line - 1; i++) + { + position += lines[i].length(); + position++; + } + return position + charPositionInLine; + } + + private Argument getFunctionArgument(CommonTree argNode, ArgumentDefinition definition, QueryModelFactory factory, + Map selectors, Map columnMap, boolean inLike) + { + if (argNode.getType() == CMISParser.COLUMN_REF) + { + PropertyArgument arg = buildColumnReference(definition.getName(), argNode, factory, selectors, columnMap); + if (!arg.isQueryable()) + { + throw new CmisInvalidArgumentException("Column refers to unqueryable property " + arg.getPropertyName()); + } + if (!selectors.containsKey(arg.getSelector())) + { + throw new CmisInvalidArgumentException("No table with alias " + arg.getSelector()); + } + return arg; + } else if (argNode.getType() == CMISParser.ID) + { + String id = argNode.getText(); + if (selectors.containsKey(id)) + { + SelectorArgument arg = factory.createSelectorArgument(definition.getName(), id); + if (!arg.isQueryable()) + { + throw new CmisInvalidArgumentException("Selector is not queryable " + arg.getSelector()); + } + return arg; + } else + { + PropertyDefinitionWrapper propDef = cmisDictionaryService.findPropertyByQueryName(id); + if (propDef == null || !propDef.getPropertyDefinition().isQueryable()) + { + throw new CmisInvalidArgumentException("Column refers to unqueryable property " + + definition.getName()); + } + PropertyArgument arg = factory.createPropertyArgument(definition.getName(), propDef + .getPropertyDefinition().isQueryable(), propDef.getPropertyDefinition().isOrderable(), "", + propDef.getPropertyId()); + return arg; + } + } else if (argNode.getType() == CMISParser.PARAMETER) + { + ParameterArgument arg = factory.createParameterArgument(definition.getName(), argNode.getText()); + if (!arg.isQueryable()) + { + throw new CmisInvalidArgumentException("Parameter is not queryable " + arg.getParameterName()); + } + return arg; + } else if (argNode.getType() == CMISParser.NUMERIC_LITERAL) + { + CommonTree literalNode = (CommonTree) argNode.getChild(0); + if (literalNode.getType() == CMISParser.FLOATING_POINT_LITERAL) + { + QName type = DataTypeDefinition.DOUBLE; + Number value = Double.parseDouble(literalNode.getText()); + if (value.floatValue() == value.doubleValue()) + { + type = DataTypeDefinition.FLOAT; + value = Float.valueOf(value.floatValue()); + } + LiteralArgument arg = factory.createLiteralArgument(definition.getName(), type, value); + return arg; + } else if (literalNode.getType() == CMISParser.DECIMAL_INTEGER_LITERAL) + { + QName type = DataTypeDefinition.LONG; + Number value = Long.parseLong(literalNode.getText()); + if (value.intValue() == value.longValue()) + { + type = DataTypeDefinition.INT; + value = Integer.valueOf(value.intValue()); + } + LiteralArgument arg = factory.createLiteralArgument(definition.getName(), type, value); + return arg; + } else + { + throw new CmisInvalidArgumentException("Invalid numeric literal " + literalNode.getText()); + } + } else if (argNode.getType() == CMISParser.STRING_LITERAL) + { + String text = argNode.getChild(0).getText(); + text = text.substring(1, text.length() - 1); + text = unescape(text, inLike ? EscapeMode.LIKE : EscapeMode.LITERAL); + LiteralArgument arg = factory.createLiteralArgument(definition.getName(), DataTypeDefinition.TEXT, text); + return arg; + } else if (argNode.getType() == CMISParser.DATETIME_LITERAL) + { + String text = argNode.getChild(0).getText(); + text = text.substring(1, text.length() - 1); + StringBuilder builder = new StringBuilder(); + if (text.endsWith("Z")) + { + builder.append(text.substring(0, text.length() - 1)); + builder.append("+0000"); + } else + { + if (text.charAt(text.length() - 3) != ':') + { + throw new CmisInvalidArgumentException("Invalid datetime literal " + text); + } + // remove TZ colon .... + builder.append(text.substring(0, text.length() - 3)); + builder.append(text.substring(text.length() - 2, text.length())); + } + text = builder.toString(); + + SimpleDateFormat df = CachingDateFormat.getCmisSqlDatetimeFormat(); + Date date; + try + { + date = df.parse(text); + } catch (ParseException e) + { + throw new CmisInvalidArgumentException("Invalid datetime literal " + text); + } + // Convert back :-) + String alfrescoDate = DefaultTypeConverter.INSTANCE.convert(String.class, date); + LiteralArgument arg = factory.createLiteralArgument(definition.getName(), DataTypeDefinition.TEXT, + alfrescoDate); + return arg; + } else if (argNode.getType() == CMISParser.BOOLEAN_LITERAL) + { + String text = argNode.getChild(0).getText(); + if (text.equalsIgnoreCase("TRUE") || text.equalsIgnoreCase("FALSE")) + { + LiteralArgument arg = factory + .createLiteralArgument(definition.getName(), DataTypeDefinition.TEXT, text); + return arg; + } else + { + throw new CmisInvalidArgumentException("Invalid boolean literal " + text); + } + + } else if (argNode.getType() == CMISParser.LIST) + { + ArrayList arguments = new ArrayList(); + for (int i = 0; i < argNode.getChildCount(); i++) + { + CommonTree arg = (CommonTree) argNode.getChild(i); + arguments.add(getFunctionArgument(arg, definition, factory, selectors, columnMap, inLike)); + } + ListArgument arg = factory.createListArgument(definition.getName(), arguments); + if (!arg.isQueryable()) + { + throw new CmisInvalidArgumentException("Not all members of the list are queryable"); + } + return arg; + } else if (argNode.getType() == CMISParser.ANY) + { + LiteralArgument arg = factory.createLiteralArgument(definition.getName(), DataTypeDefinition.TEXT, + argNode.getText()); + return arg; + } else if (argNode.getType() == CMISParser.SINGLE_VALUED_PROPERTY) + { + LiteralArgument arg = factory.createLiteralArgument(definition.getName(), DataTypeDefinition.TEXT, + argNode.getText()); + return arg; + } else if (argNode.getType() == CMISParser.NOT) + { + LiteralArgument arg = factory.createLiteralArgument(definition.getName(), DataTypeDefinition.TEXT, + argNode.getText()); + return arg; + } else if (argNode.getType() == CMISParser.FUNCTION) + { + CommonTree functionNameNode = (CommonTree) argNode.getChild(0); + Function function = factory.getFunction(functionNameNode.getText()); + if (function == null) + { + throw new CmisInvalidArgumentException("Unknown function: " + functionNameNode.getText()); + } + Collection definitions = function.getArgumentDefinitions().values(); + Map functionArguments = new LinkedHashMap(); + + int childIndex = 2; + for (ArgumentDefinition currentDefinition : definitions) + { + if (argNode.getChildCount() > childIndex + 1) + { + CommonTree currentArgNode = (CommonTree) argNode.getChild(childIndex++); + Argument arg = getFunctionArgument(currentArgNode, currentDefinition, factory, selectors, + columnMap, inLike); + functionArguments.put(arg.getName(), arg); + } else + { + if (definition.isMandatory()) + { + // throw new CmisInvalidArgumentException("Insufficient + // aruments + // for function " + ((CommonTree) + // functionNode.getChild(0)).getText() ); + break; + } else + { + // ok + } + } + } + FunctionArgument arg = factory.createFunctionArgument(definition.getName(), function, functionArguments); + if (!arg.isQueryable()) + { + throw new CmisInvalidArgumentException("Not all function arguments refer to orderable arguments: " + + arg.getFunction().getName()); + } + return arg; + } else + { + throw new CmisInvalidArgumentException("Invalid function argument " + argNode.getText()); + } + } + + @SuppressWarnings("unchecked") + private Source buildSource(CommonTree source, CapabilityJoin joinSupport, QueryModelFactory factory, JoinType lhsJoin) + { + if (source.getChildCount() == 1) + { + // single table reference + CommonTree singleTableNode = (CommonTree) source.getChild(0); + if (singleTableNode.getType() == CMISParser.TABLE) + { + if (joinSupport == CapabilityJoin.NONE) + { + throw new UnsupportedOperationException("Joins are not supported"); + } + CommonTree tableSourceNode = (CommonTree) singleTableNode.getFirstChildWithType(CMISParser.SOURCE); + return buildSource(tableSourceNode, joinSupport, factory, JoinType.NONE); + + } + if (singleTableNode.getType() != CMISParser.TABLE_REF) + { + throw new CmisInvalidArgumentException("Expecting TABLE_REF token but found " + + singleTableNode.getText()); + } + String tableName = singleTableNode.getChild(0).getText(); + String alias = ""; + if (singleTableNode.getChildCount() > 1) + { + alias = singleTableNode.getChild(1).getText(); + } + + TypeDefinitionWrapper typeDef = cmisDictionaryService.findTypeByQueryName(tableName); + if (typeDef == null) + { + throw new CmisInvalidArgumentException("Type is unsupported in query: " + tableName); + } + if (typeDef.getBaseTypeId() != BaseTypeId.CMIS_POLICY) + { + if (!typeDef.getTypeDefinition(false).isQueryable()) + { + throw new CmisInvalidArgumentException("Type is not queryable " + tableName + " -> " + + typeDef.getTypeId()); + } + } + Source lhs = factory.createSelector(typeDef.getAlfrescoClass(), alias); + lhs.setJoinType(lhsJoin); + return lhs; + } else + { + if (joinSupport == CapabilityJoin.NONE) + { + throw new UnsupportedOperationException("Joins are not supported"); + } + CommonTree singleTableNode = (CommonTree) source.getChild(0); + if (singleTableNode.getType() != CMISParser.TABLE_REF) + { + throw new CmisInvalidArgumentException("Expecting TABLE_REF token but found " + + singleTableNode.getText()); + } + String tableName = singleTableNode.getChild(0).getText(); + String alias = ""; + if (singleTableNode.getChildCount() == 2) + { + alias = singleTableNode.getChild(1).getText(); + } + TypeDefinitionWrapper typeDef = cmisDictionaryService.findTypeByQueryName(tableName); + if (typeDef == null) + { + throw new CmisInvalidArgumentException("Type is unsupported in query " + tableName); + } + if (typeDef.getBaseTypeId() != BaseTypeId.CMIS_POLICY) + { + if (!typeDef.getTypeDefinition(false).isQueryable()) + { + throw new CmisInvalidArgumentException("Type is not queryable " + tableName + " -> " + + typeDef.getTypeId()); + } + } + + Source lhs = factory.createSelector(typeDef.getAlfrescoClass(), alias); + if(lhsJoin == JoinType.NONE) + { + lhs.setJoinType(JoinType.INNER); + } + else + { + lhs.setJoinType(lhsJoin); + } + + List list = (List) (source.getChildren()); + for (CommonTree joinNode : list) + { + if (joinNode.getType() == CMISParser.JOIN) + { + JoinType joinType = JoinType.INNER; + CommonTree joinTypeNode = (CommonTree) joinNode.getFirstChildWithType(CMISParser.LEFT); + if (joinTypeNode != null) + { + joinType = JoinType.LEFT; + } + + if ((joinType == JoinType.LEFT) && (joinSupport != CapabilityJoin.INNERANDOUTER)) + { + throw new UnsupportedOperationException("Outer joins are not supported"); + } + + CommonTree rhsSource = (CommonTree) joinNode.getFirstChildWithType(CMISParser.SOURCE); + Source rhs = buildSource(rhsSource, joinSupport, factory, joinType); + + Constraint joinCondition = null; + CommonTree joinConditionNode = (CommonTree) joinNode.getFirstChildWithType(CMISParser.ON); + if (joinConditionNode != null) + { + PropertyArgument arg1 = buildColumnReference(Equals.ARG_LHS, + (CommonTree) joinConditionNode.getChild(0), factory, null, null); + if (!lhs.getSelectors().containsKey(arg1.getSelector()) + && !rhs.getSelectors().containsKey(arg1.getSelector())) + { + throw new CmisInvalidArgumentException("No table with alias " + arg1.getSelector()); + } + CommonTree functionNameNode = (CommonTree) joinConditionNode.getChild(1); + if (functionNameNode.getType() != CMISParser.EQUALS) + { + throw new CmisInvalidArgumentException("Only Equi-join is supported " + + functionNameNode.getText()); + } + Function function = factory.getFunction(Equals.NAME); + if (function == null) + { + throw new CmisInvalidArgumentException("Unknown function: " + functionNameNode.getText()); + } + PropertyArgument arg2 = buildColumnReference(Equals.ARG_RHS, + (CommonTree) joinConditionNode.getChild(2), factory, null, null); + if (!lhs.getSelectors().containsKey(arg2.getSelector()) + && !rhs.getSelectors().containsKey(arg2.getSelector())) + { + throw new CmisInvalidArgumentException("No table with alias " + arg2.getSelector()); + } + Map functionArguments = new LinkedHashMap(); + functionArguments.put(arg1.getName(), arg1); + functionArguments.put(arg2.getName(), arg2); + joinCondition = factory.createFunctionalConstraint(function, functionArguments); + } + + Source join = factory.createJoin(lhs, rhs, joinType, joinCondition); + lhs = join; + } + } + + return lhs; + + } + } + + public PropertyArgument buildColumnReference(String argumentName, CommonTree columnReferenceNode, + QueryModelFactory factory, Map selectors, Map columnMap) + { + String cmisPropertyName = columnReferenceNode.getChild(0).getText(); + String qualifier = ""; + if (columnReferenceNode.getChildCount() > 1) + { + qualifier = columnReferenceNode.getChild(1).getText(); + } + + if ((qualifier == "") && (columnMap != null)) + { + Column column = columnMap.get(cmisPropertyName); + if (column != null) + { + // check for function type + if (column.getFunction().getName().equals(PropertyAccessor.NAME)) + { + PropertyArgument arg = (PropertyArgument) column.getFunctionArguments().get( + PropertyAccessor.ARG_PROPERTY); + cmisPropertyName = arg.getPropertyName(); + qualifier = arg.getSelector(); + } else + { + // TODO: should be able to return non property arguments + // The implementation should throw out what it can not + // support at build time. + throw new CmisInvalidArgumentException( + "Complex column reference unsupported (only direct column references are currently supported) " + + cmisPropertyName); + } + } + } + + PropertyDefinitionWrapper propDef = cmisDictionaryService.findPropertyByQueryName(cmisPropertyName); + if (propDef == null) + { + throw new CmisInvalidArgumentException("Unknown column/property " + cmisPropertyName); + } + + if (selectors != null) + { + Selector selector = selectors.get(qualifier); + if (selector == null) + { + if ((qualifier.equals("")) && (selectors.size() == 1)) + { + selector = selectors.get(selectors.keySet().iterator().next()); + } else + { + throw new CmisInvalidArgumentException("No selector for " + qualifier); + } + } + + TypeDefinitionWrapper typeDef = cmisDictionaryService.findTypeForClass(selector.getType(), validScopes); + if (typeDef == null) + { + throw new CmisInvalidArgumentException("Type unsupported in CMIS queries: " + selector.getAlias()); + } + + // Check column/property applies to selector/type + + if (typeDef.getPropertyById(propDef.getPropertyId()) == null) + { + throw new CmisInvalidArgumentException("Invalid column for " + + typeDef.getTypeDefinition(false).getQueryName() + "." + cmisPropertyName); + } + } + + if (options.getQueryMode() == CMISQueryMode.CMS_STRICT) + { + if (!propDef.getPropertyDefinition().isQueryable()) + { + throw new CmisInvalidArgumentException("Column is not queryable " + qualifier + "." + cmisPropertyName); + } + } + return factory.createPropertyArgument(argumentName, propDef.getPropertyDefinition().isQueryable(), propDef + .getPropertyDefinition().isOrderable(), qualifier, propDef.getPropertyId()); + } + + private String unescape(String string, EscapeMode mode) + { + StringBuilder builder = new StringBuilder(string.length()); + + boolean lastWasEscape = false; + + for (int i = 0; i < string.length(); i++) + { + char c = string.charAt(i); + if (lastWasEscape) + { + + // Need to keep escaping for like as we have the same escaping + if (mode == EscapeMode.LIKE) + { + // Like does its own escaping - so pass through \ % and _ + if (c == '\'') + { + builder.append(c); + } else if (c == '%') + { + builder.append('\\'); + builder.append(c); + } else if (c == '_') + { + builder.append('\\'); + builder.append(c); + } else if (c == '\\') + { + builder.append('\\'); + builder.append(c); + } else + { + throw new UnsupportedOperationException("Unsupported escape pattern in <" + string + + "> at position " + i); + } + } else if (mode == EscapeMode.CONTAINS) + { + if (options.getQueryMode() == CMISQueryMode.CMS_STRICT) + { + if (c == '\'') + { + builder.append(c); + } else if (c == '\\') + { + builder.append('\\'); + builder.append(c); + } + + else + { + throw new UnsupportedOperationException("Unsupported escape pattern in <" + string + + "> at position " + i); + } + } else + { + if (c == '\'') + { + builder.append(c); + } else + { + builder.append(c); + } + } + } else if (mode == EscapeMode.LITERAL) + { + if (c == '\'') + { + builder.append(c); + } else if (c == '\\') + { + builder.append(c); + } else + { + throw new UnsupportedOperationException("Unsupported escape pattern in <" + string + + "> at position " + i); + + } + } else + { + throw new UnsupportedOperationException("Unsupported escape pattern in <" + string + + "> at position " + i); + + } + lastWasEscape = false; + } else + { + if (c == '\\') + { + lastWasEscape = true; + } else + { + builder.append(c); + } + } + } + if (lastWasEscape) + { + throw new FTSQueryException("Escape character at end of string " + string); + } + + return builder.toString(); + } +} diff --git a/data-model/src/main/java/org/alfresco/opencmis/search/CmisFunctionEvaluationContext.java b/data-model/src/main/java/org/alfresco/opencmis/search/CmisFunctionEvaluationContext.java new file mode 100644 index 0000000000..b349e2bffe --- /dev/null +++ b/data-model/src/main/java/org/alfresco/opencmis/search/CmisFunctionEvaluationContext.java @@ -0,0 +1,554 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.search; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; + +import org.alfresco.opencmis.dictionary.CMISDictionaryService; +import org.alfresco.opencmis.dictionary.CMISNodeInfo; +import org.alfresco.opencmis.dictionary.PropertyDefinitionWrapper; +import org.alfresco.opencmis.dictionary.TypeDefinitionWrapper; +import org.alfresco.repo.search.adaptor.lucene.LuceneFunction; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.adaptor.lucene.QueryConstants; +import org.alfresco.repo.search.impl.querymodel.FunctionArgument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.Selector; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Lower; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Upper; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.apache.chemistry.opencmis.commons.PropertyIds; +import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; +import org.apache.chemistry.opencmis.commons.enums.Cardinality; +import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; + +/** + * @author andyh + */ +@SuppressWarnings("deprecation") +public class CmisFunctionEvaluationContext implements FunctionEvaluationContext +{ + private static HashSet EXPOSED_FIELDS = new HashSet(); + + public static BaseTypeId[] STRICT_SCOPES = new BaseTypeId[] { BaseTypeId.CMIS_DOCUMENT, BaseTypeId.CMIS_FOLDER }; + + public static BaseTypeId[] ALFRESCO_SCOPES = new BaseTypeId[] { BaseTypeId.CMIS_DOCUMENT, BaseTypeId.CMIS_FOLDER, + BaseTypeId.CMIS_POLICY, BaseTypeId.CMIS_SECONDARY, BaseTypeId.CMIS_ITEM }; + + private Map nodeRefs; + + private Map scores; + + private Map nodeInfos; + + private NodeService nodeService; + + private CMISDictionaryService cmisDictionaryService; + + private BaseTypeId[] validScopes; + + private Float score; + + static + { + EXPOSED_FIELDS.add(QueryConstants.FIELD_PATH); + EXPOSED_FIELDS.add(QueryConstants.FIELD_TEXT); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ID); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ISROOT); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ISNODE); + EXPOSED_FIELDS.add(QueryConstants.FIELD_TX); + EXPOSED_FIELDS.add(QueryConstants.FIELD_PARENT); + EXPOSED_FIELDS.add(QueryConstants.FIELD_PRIMARYPARENT); + EXPOSED_FIELDS.add(QueryConstants.FIELD_QNAME); + EXPOSED_FIELDS.add(QueryConstants.FIELD_CLASS); + EXPOSED_FIELDS.add(QueryConstants.FIELD_TYPE); + EXPOSED_FIELDS.add(QueryConstants.FIELD_EXACTTYPE); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ASPECT); + EXPOSED_FIELDS.add(QueryConstants.FIELD_EXACTASPECT); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ALL); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ISUNSET); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ISNULL); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ISNOTNULL); + EXPOSED_FIELDS.add(QueryConstants.FIELD_FTSSTATUS); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ASSOCTYPEQNAME); + EXPOSED_FIELDS.add(QueryConstants.FIELD_PRIMARYASSOCTYPEQNAME); + EXPOSED_FIELDS.add(QueryConstants.FIELD_DBID); + EXPOSED_FIELDS.add(QueryConstants.FIELD_TAG); + EXPOSED_FIELDS.add(QueryConstants.FIELD_TENANT); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ANCESTOR); + EXPOSED_FIELDS.add(QueryConstants.FIELD_SITE); + EXPOSED_FIELDS.add(QueryConstants.FIELD_TAG); + EXPOSED_FIELDS.add(QueryConstants.FIELD_PNAME); + EXPOSED_FIELDS.add(QueryConstants.FIELD_NPATH); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ANAME); + EXPOSED_FIELDS.add(QueryConstants.FIELD_APATH); + EXPOSED_FIELDS.add(QueryConstants.FIELD_DOC_TYPE); + + + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.ANY.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.ASSOC_REF.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.BOOLEAN.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.CATEGORY.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.CHILD_ASSOC_REF.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.CONTENT.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.DATE.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.DATETIME.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.DOUBLE.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.FLOAT.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.INT.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.LOCALE.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.LONG.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.MLTEXT.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.NODE_REF.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.PATH.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.PERIOD.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.QNAME.getLocalName()); + EXPOSED_FIELDS.add("d:"+DataTypeDefinition.TEXT.getLocalName()); + } + + + /** + * @param nodeRefs + * the nodeRefs to set + */ + public void setNodeRefs(Map nodeRefs) + { + this.nodeRefs = nodeRefs; + } + + /** + * @param scores + * the scores to set + */ + public void setScores(Map scores) + { + this.scores = scores; + } + + public void setNodeInfos(Map nodeInfos) { + this.nodeInfos = nodeInfos; + } + + /** + * @param nodeService + * the nodeService to set + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + /** + * @param cmisDictionaryService + * the cmisDictionaryService to set + */ + public void setCmisDictionaryService(CMISDictionaryService cmisDictionaryService) + { + this.cmisDictionaryService = cmisDictionaryService; + } + + /** + * @param validScopes + * the valid scopes to set + */ + public void setValidScopes(BaseTypeId[] validScopes) + { + this.validScopes = validScopes; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext# + * getNodeRefs() + */ + public Map getNodeRefs() + { + return nodeRefs; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext# + * getNodeService() + */ + public NodeService getNodeService() + { + return nodeService; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext# + * getProperty(org.alfresco.service.cmr.repository.NodeRef, + * org.alfresco.service.namespace.QName) + */ + public Serializable getProperty(NodeRef nodeRef, String propertyName) + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName); + + CMISNodeInfo nodeInfo = nodeInfos.get(nodeRef); + if (nodeInfo == null) + { + nodeInfo = propertyDef.getPropertyAccessor().createNodeInfo(nodeRef); + nodeInfos.put(nodeRef, nodeInfo); + } + + return propertyDef.getPropertyAccessor().getValue(nodeInfo); + } + + /* + * (non-Javadoc) + * + * @see + * org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#getScores + * () + */ + public Map getScores() + { + return scores; + } + + /** + * @return the score + */ + public Float getScore() + { + return score; + } + + /** + * @param score + * the score to set + */ + public void setScore(Float score) + { + this.score = score; + } + + public Q buildLuceneEquality(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, + PredicateMode mode, LuceneFunction luceneFunction) throws E + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName); + return propertyDef.getPropertyLuceneBuilder().buildLuceneEquality(lqpa, value, mode, luceneFunction); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext# + * buildLuceneExists(org.alfresco.repo.search.impl.lucene.LuceneQueryParser, + * org.alfresco.service.namespace.QName, java.lang.Boolean) + */ + public Q buildLuceneExists(LuceneQueryParserAdaptor lqpa, String propertyName, Boolean not) throws E + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName); + return propertyDef.getPropertyLuceneBuilder().buildLuceneExists(lqpa, not); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext# + * buildLuceneGreaterThan + * (org.alfresco.repo.search.impl.lucene.LuceneQueryParser, + * org.alfresco.service.namespace.QName, java.io.Serializable, + * org.alfresco.repo.search.impl.querymodel.PredicateMode) + */ + public Q buildLuceneGreaterThan(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, + PredicateMode mode, LuceneFunction luceneFunction) throws E + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName); + return propertyDef.getPropertyLuceneBuilder().buildLuceneGreaterThan(lqpa, value, mode, luceneFunction); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext# + * buildLuceneGreaterThanOrEquals + * (org.alfresco.repo.search.impl.lucene.LuceneQueryParser, + * org.alfresco.service.namespace.QName, java.io.Serializable, + * org.alfresco.repo.search.impl.querymodel.PredicateMode) + */ + public Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, + PredicateMode mode, LuceneFunction luceneFunction) throws E + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName); + return propertyDef.getPropertyLuceneBuilder().buildLuceneGreaterThanOrEquals(lqpa, value, mode, luceneFunction); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext# + * buildLuceneIn(org.alfresco.repo.search.impl.lucene.LuceneQueryParser, + * org.alfresco.service.namespace.QName, java.util.Collection, + * java.lang.Boolean, + * org.alfresco.repo.search.impl.querymodel.PredicateMode) + */ + public Q buildLuceneIn(LuceneQueryParserAdaptor lqpa, String propertyName, Collection values, + Boolean not, PredicateMode mode) throws E + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName); + return propertyDef.getPropertyLuceneBuilder().buildLuceneIn(lqpa, values, not, mode); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext# + * buildLuceneInequality + * (org.alfresco.repo.search.impl.lucene.LuceneQueryParser, + * org.alfresco.service.namespace.QName, java.io.Serializable, + * org.alfresco.repo.search.impl.querymodel.PredicateMode) + */ + public Q buildLuceneInequality(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, + PredicateMode mode, LuceneFunction luceneFunction) throws E + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName); + return propertyDef.getPropertyLuceneBuilder().buildLuceneInequality(lqpa, value, mode, luceneFunction); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext# + * buildLuceneLessThan + * (org.alfresco.repo.search.impl.lucene.LuceneQueryParser, + * org.alfresco.service.namespace.QName, java.io.Serializable, + * org.alfresco.repo.search.impl.querymodel.PredicateMode) + */ + public Q buildLuceneLessThan(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, + PredicateMode mode, LuceneFunction luceneFunction) throws E + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName); + return propertyDef.getPropertyLuceneBuilder().buildLuceneLessThan(lqpa, value, mode, luceneFunction); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext# + * buildLuceneLessThanOrEquals + * (org.alfresco.repo.search.impl.lucene.LuceneQueryParser, + * org.alfresco.service.namespace.QName, java.io.Serializable, + * org.alfresco.repo.search.impl.querymodel.PredicateMode) + */ + public Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, + PredicateMode mode, LuceneFunction luceneFunction) throws E + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName); + return propertyDef.getPropertyLuceneBuilder().buildLuceneLessThanOrEquals(lqpa, value, mode, luceneFunction); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext# + * buildLuceneLike(org.alfresco.repo.search.impl.lucene.LuceneQueryParser, + * org.alfresco.service.namespace.QName, java.io.Serializable, + * java.lang.Boolean) + */ + public Q buildLuceneLike(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, Boolean not) + throws E + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName); + return propertyDef.getPropertyLuceneBuilder().buildLuceneLike(lqpa, value, not); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext# + * getLuceneSortField(org.alfresco.service.namespace.QName) + */ + public String getLuceneSortField(LuceneQueryParserAdaptor lqpa, String propertyName) throws E + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName); + return propertyDef.getPropertyLuceneBuilder().getLuceneSortField(lqpa); + } + + public boolean isObjectId(String propertyName) + { + return PropertyIds.OBJECT_ID.equalsIgnoreCase(propertyName); + } + + public boolean isOrderable(String fieldName) + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(fieldName); + if (propertyDef == null) + { + return false; + } else + { + return propertyDef.getPropertyDefinition().isOrderable(); + } + } + + public boolean isQueryable(String fieldName) + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(fieldName); + if (propertyDef == null) + { + return true; + } else + { + return propertyDef.getPropertyDefinition().isQueryable(); + } + } + + public String getLuceneFieldName(String propertyName) + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName); + if (propertyDef != null) + { + return propertyDef.getPropertyLuceneBuilder().getLuceneFieldName(); + } else + { + // TODO: restrict to supported "special" fields + return propertyName; + } + } + + public LuceneFunction getLuceneFunction(FunctionArgument functionArgument) + { + if (functionArgument == null) + { + return LuceneFunction.FIELD; + } else + { + String functionName = functionArgument.getFunction().getName(); + if (functionName.equals(Upper.NAME)) + { + return LuceneFunction.UPPER; + } else if (functionName.equals(Lower.NAME)) + { + return LuceneFunction.LOWER; + } else + { + throw new QueryModelException("Unsupported function: " + functionName); + } + } + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext# + * checkFieldApplies(org.alfresco.service.namespace.QName, java.lang.String) + */ + public void checkFieldApplies(Selector selector, String propertyName) + { + PropertyDefinitionWrapper propDef = cmisDictionaryService.findPropertyByQueryName(propertyName); + if (propDef == null) + { + if (EXPOSED_FIELDS.contains(propertyName)) + { + return; + } + else + { + throw new CmisInvalidArgumentException("Unknown column/property " + propertyName); + } + } + + TypeDefinitionWrapper typeDef = cmisDictionaryService.findTypeForClass(selector.getType(), validScopes); + if (typeDef == null) + { + throw new CmisInvalidArgumentException("Type unsupported in CMIS queries: " + selector.getAlias()); + } + + // Check column/property applies to selector/type + + if (typeDef.getPropertyById(propDef.getPropertyId()) == null) + { + throw new CmisInvalidArgumentException("Invalid column for " + + typeDef.getTypeDefinition(false).getQueryName() + "." + propertyName); + } + + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext# + * isMultiValued(java.lang.String) + */ + public boolean isMultiValued(String propertyName) + { + PropertyDefinitionWrapper propDef = cmisDictionaryService.findPropertyByQueryName(propertyName); + if (propDef == null) + { + throw new CmisInvalidArgumentException("Unknown column/property " + propertyName); + } + return propDef.getPropertyDefinition().getCardinality() == Cardinality.MULTI; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#getAlfrescoQName(org.alfresco.service.namespace.QName) + */ + @Override + public String getAlfrescoPropertyName(String propertyName) + { + PropertyDefinitionWrapper propertyDef = cmisDictionaryService.findProperty(propertyName); + if(propertyDef != null) + { + return propertyDef.getPropertyLuceneBuilder().getLuceneFieldName().substring(1); + } + else + { + throw new CmisInvalidArgumentException("Unknown column/property " + propertyName); + } + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#getAlfrescoTypeName(java.lang.String) + */ + @Override + public String getAlfrescoTypeName(String typeName) + { + TypeDefinitionWrapper typeDef = cmisDictionaryService.findType(typeName); + if(typeDef != null) + { + return typeDef.getAlfrescoClass().toString(); + } + else + { + throw new CmisInvalidArgumentException("Unknown type " + typeName); + } + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/cache/LockingCache.java b/data-model/src/main/java/org/alfresco/repo/cache/LockingCache.java new file mode 100644 index 0000000000..316d265762 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/cache/LockingCache.java @@ -0,0 +1,61 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.cache; + +import java.io.Serializable; + +/** + * Interface for caches that support value locking + * + * @author Derek Hulley + * @since 4.1.6 + */ +public interface LockingCache extends SimpleCache +{ + /** + * Determine if a value (addition, removal or update) has been locked for the remainer of the transaction + * + * @param key the cache key to check up on + * @return true if the value will not change for the remaineder of the transaction + */ + boolean isValueLocked(K key); + + /** + * Prevent a key's value from being changed for the duriation of the transaction. + * By default, further attempts to modify the associated value will be ignored; + * this includes add a value back after removal. + * + * @param key the cache key that will be locked against change + */ + void lockValue(K key); + + /** + * Cancel any previous lock applied to a key's value. + * + * @param key the cache key that will be unlocked, allowing changes + */ + void unlockValue(K key); +} diff --git a/data-model/src/main/java/org/alfresco/repo/cache/MemoryCache.java b/data-model/src/main/java/org/alfresco/repo/cache/MemoryCache.java new file mode 100644 index 0000000000..882760b322 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/cache/MemoryCache.java @@ -0,0 +1,79 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.cache; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * A cache backed by a simple ConcurrentHashMap. + *

+ * Note: This cache is not transaction-safe. Use it for tests or wrap it appropriately. + * + * @author Derek Hulley + * @since 3.2 + */ +public class MemoryCache implements SimpleCache +{ + private Map map; + + public MemoryCache() + { + map = new ConcurrentHashMap(15); + } + + public boolean contains(K key) + { + return map.containsKey(key); + } + + public Collection getKeys() + { + return map.keySet(); + } + + public V get(K key) + { + return map.get(key); + } + + public void put(K key, V value) + { + map.put(key, value); + } + + public void remove(K key) + { + map.remove(key); + } + + public void clear() + { + map.clear(); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/cache/SimpleCache.java b/data-model/src/main/java/org/alfresco/repo/cache/SimpleCache.java new file mode 100644 index 0000000000..eb49ea713d --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/cache/SimpleCache.java @@ -0,0 +1,93 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.cache; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Map; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Basic caching interface. + *

+ * All implementations must be thread-safe. Additionally, the use of the + * Serializable for both keys and values ensures that the underlying + * cache implementations can support both clustered caches as well as persistent + * caches. + *

+ * All implementations must support null values. It therefore follows + * that + *

+ *    (simpleCache.contains(key) == true) does not imply (simpleCache.get(key) != null)
+ * 
+ * but + *
+ *    (simpleCache.contains(key) == false) implies (simpleCache.get(key) == null)
+ * 
+ * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public interface SimpleCache +{ + /** + * @param key the cache key to check up on + * @return Returns true if there is a cache entry, + * regardless of whether the value itself is null + */ + public boolean contains(K key); + + public Collection getKeys(); + + /** + * @param key K + * @return Returns the value associated with the key. It will be null + * if the value is null or if the cache doesn't have an entry. + */ + public V get(K key); + + /** + * Set the value to store for a given key. + *

+ * Be sure to use {@link #remove(Serializable) remove} if cache entries need to be removed + * as the cache implementations must treat a null value as a first class object + * in exactly the same way as a {@link Map} will allow storage and retrieval of null values. + * + * @param key the key against which to store the value + * @param value the value to store. null is allowed. + */ + public void put(K key, V value); + + /** + * Removes the cache entry whether or not the value stored against it is null. + * + * @param key the key value to remove + */ + public void remove(K key); + + public void clear(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/content/ContentContext.java b/data-model/src/main/java/org/alfresco/repo/content/ContentContext.java new file mode 100644 index 0000000000..7ff9bf3ab3 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/content/ContentContext.java @@ -0,0 +1,92 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content; + +import java.io.Serializable; + +import org.alfresco.service.cmr.repository.ContentReader; + +/** + * The location and lookup data for content. The very least data required to + * find content or assign a content writer is the content URL and any previous + * content that may have logically existed. + *

+ * Although this class is doesn't enforce any conditions on the context, + * derived instances may have relationships that need to be maintained between + * various context values. + * + * @author Derek Hulley + */ +public class ContentContext implements Serializable +{ + private static final long serialVersionUID = 6476617391229895125L; + + /** An empty context. */ + public static final ContentContext NULL_CONTEXT = new ContentContext(null, null); + + private ContentReader existingContentReader; + private String contentUrl; + + /** + * Construct the instance with the content URL. + * + * @param existingContentReader content with which to seed the new writer - may be null + * @param contentUrl the content URL - may be null + */ + public ContentContext(ContentReader existingContentReader, String contentUrl) + { + this.existingContentReader = existingContentReader; + this.contentUrl = contentUrl; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(128); + sb.append("ContentContext") + .append("[ contentUrl=").append(getContentUrl()) + .append(", existing=").append((getExistingContentReader() == null ? false : true)) + .append("]"); + return sb.toString(); + } + + /** + * @return Returns the content to seed the writer with - may be null + */ + public ContentReader getExistingContentReader() + { + return existingContentReader; + } + + /** + * @return Returns the content URL for the content's context - may be null + */ + public String getContentUrl() + { + return contentUrl; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/content/ContentStore.java b/data-model/src/main/java/org/alfresco/repo/content/ContentStore.java new file mode 100644 index 0000000000..741427c522 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/content/ContentStore.java @@ -0,0 +1,238 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.cmr.repository.ContentAccessor; +import org.alfresco.service.cmr.repository.ContentIOException; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentStreamListener; +import org.alfresco.service.cmr.repository.ContentWriter; + +/** + * Provides low-level retrieval of content + * {@link org.alfresco.service.cmr.repository.ContentReader readers} and + * {@link org.alfresco.service.cmr.repository.ContentWriter writers}. + *

+ * Implementations of this interface should be soley responsible for + * providing persistence and retrieval of the content against a + * content URL. + *

+ * Content URLs must consist of a prefix or protocol followed by an + * implementation-specific identifier. See + * {@link org.alfresco.repo.content.filestore.TimeBasedFileContentUrlProvider TimeBasedFileContentUrlProvider} and + * {@link org.alfresco.repo.content.filestore.VolumeAwareContentUrlProvider VolumeAwareContentUrlProvider} implementations of + * {@link org.alfresco.repo.content.filestore.FileContentUrlProvider FileContentUrlProvider} + * For example, default content URL format + * for file stores is store://year/month/day/hour/minute/GUID.bin
+ *

    + *
  • store://: prefix identifying an Alfresco content stores + * regardless of the persistence mechanism.
  • + *
  • year: year
  • + *
  • month: 1-based month of the year
  • + *
  • day: 1-based day of the month
  • + *
  • hour: 0-based hour of the day
  • + *
  • minute: 0-based minute of the hour
  • + *
  • GUID: A unique identifier
  • + *
+ *

+ * Where the store cannot handle a particular content URL request, the + * {@code UnsupportedContentUrlException} must be generated. This will allow + * various implementations to provide fallback code to other stores where + * possible. + *

+ * Where a store cannot serve a particular request because the functionality + * is just not available, the UnsupportedOperationException should + * be thrown. Once again, there may be fallback handling provided for these + * situations. + * + * @since 1.0 + * @author Derek Hulley + */ +@AlfrescoPublicApi +public interface ContentStore +{ + /** + * An empty content context used to retrieve completely new content. + * + * @see ContentStore#getWriter(ContentContext) + */ + public static final ContentContext NEW_CONTENT_CONTEXT = new ContentContext(null, null); + /** + * The delimiter that must be found in all URLS, i.e :// + */ + public static final String PROTOCOL_DELIMITER = "://"; + + /** + * Check if the content URL format is supported by the store. + * + * @param contentUrl the content URL to check + * @return Returns true if none of the other methods on the store + * will throw an {@code UnsupportedContentUrlException} when given + * this URL. + * + * @since 2.1 + */ + public boolean isContentUrlSupported(String contentUrl); + + /** + * Check if the store supports write requests. + * + * @return Return true is the store supports write operations + * + * @since 2.1 + */ + public boolean isWriteSupported(); + + /** + * Calculates the remaning free space in the underlying store. + *

+ * NOTE: For efficiency, some implementations may provide a guess. + *

+ * Implementations should focus on calculating a size value quickly, rather than accurately. + * + * @return + * Returns the total, possibly approximate, free space (in bytes) available to the store + * or -1 if no size data is available. + * + * @since 3.3.3 + */ + public long getSpaceFree(); + + /** + * Calculates the total storage space of the underlying store. + *

+ * NOTE: For efficiency, some implementations may provide a guess. + *

+ * Implementations should focus on calculating a size value quickly, rather than accurately. + * + * @return + * Returns the total, possibly approximate, size (in bytes) of the underlying store + * or -1 if no size data is available. + * + * @since 3.3.3 + */ + public long getSpaceTotal(); + + /** + * Get the location where the store is rooted. The format of the returned value will depend on the + * specific implementation of the store. + * + * @return Returns the store's root location or . if no information is available + */ + public String getRootLocation(); + + /** + * Check for the existence of content in the store. + *

+ * The implementation of this may be more efficient than first getting a + * reader to {@link ContentReader#exists() check for existence}, although + * that check should also be performed. + * + * @param contentUrl + * the path to the content + * @return + * Returns true if the content exists, otherwise false if the content doesn't + * exist or if the URL is not applicable to this store. + * @throws org.alfresco.repo.content.UnsupportedContentUrlException + * if the content URL supplied is not supported by the store + * @throws ContentIOException + * if an IO error occurs + * + * @see ContentReader#exists() + */ + public boolean exists(String contentUrl); + + /** + * Get the accessor with which to read from the content at the given URL. + * The reader is stateful and can only be used once. + * + * @param contentUrl the path to where the content is located + * @return Returns a read-only content accessor for the given URL. There may + * be no content at the given URL, but the reader must still be returned. + * @throws org.alfresco.repo.content.UnsupportedContentUrlException + * if the content URL supplied is not supported by the store + * @throws ContentIOException + * if an IO error occurs + * + * @see #exists(String) + * @see ContentReader#exists() + * @see org.alfresco.repo.content.EmptyContentReader + */ + public ContentReader getReader(String contentUrl); + + /** + * Get an accessor with which to write content to a location + * within the store. The writer is stateful and can + * only be used once. The location may be specified but must, in that case, + * be a valid and unused URL. + *

+ * The store will ensure that the {@link ContentAccessor#getContentUrl() new content URL} will + * be valid for all subsequent read attempts. + *

+ * By supplying a reader to existing content, the store implementation may + * enable random access. The store implementation + * can enable this by copying the existing content into the new location + * before supplying a writer onto the new content. + * + * @param context + * the context of content. + * @return + * Returns a write-only content accessor + * @throws UnsupportedOperationException + * if the store is unable to provide the information + * @throws UnsupportedContentUrlException + * if the content URL supplied is not supported by the store + * @throws ContentExistsException + * if the content URL is already in use + * @throws ContentIOException + * if an IO error occurs + * + * @see ContentWriter#addListener(ContentStreamListener) + * @see ContentWriter#getContentUrl() + */ + public ContentWriter getWriter(ContentContext context); + + /** + * Deletes the content at the given URL. + *

+ * A delete cannot be forced since it is much better to have the + * file remain longer than desired rather than deleted prematurely. + * + * @param contentUrl + * the URL of the content to delete + * @return + * Returns true if the content was deleted (either by this or another operation), + * otherwise false. If the content no longer exists, then true is returned. + * @throws UnsupportedOperationException + * if the store is unable to perform the action + * @throws UnsupportedContentUrlException + * if the content URL supplied is not supported by the store + * @throws ContentIOException if an error occurs + * if an IO error occurs + */ + public boolean delete(String contentUrl); +} diff --git a/data-model/src/main/java/org/alfresco/repo/content/ContentStoreCaps.java b/data-model/src/main/java/org/alfresco/repo/content/ContentStoreCaps.java new file mode 100644 index 0000000000..44bdd26744 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/content/ContentStoreCaps.java @@ -0,0 +1,59 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content; + +import org.alfresco.repo.tenant.TenantDeployer; + +/** + * ContentStore capabilities. Allows us to avoid performing {@code instanceof} questions + * which can become a problem when certain proxies or subsystems are in use. + *

+ * See ACE-2682 (tenant creation failure) for motivation. + * + * @author Matt Ward + */ +public interface ContentStoreCaps +{ + /** + * Returns the ContentStore cast to a TenantRoutingContentStore if the underlying + * instance is of that type. Returns null otherwise. + *

+ * Note, the actual return type is a TenantDeployer (supertype of TenantRoutingContentStore) + * since the data model has no knowledge of that subtype. This interface may + * need to move to a different project. + * + * @return TenantRoutingContentStore + */ + TenantDeployer getTenantRoutingContentStore(); + + /** + * Returns the ContentStore cast to a TenantDeployer if the underlying + * instance is of that type. Returns null otherwise. + * + * @return TenantDeployer + */ + TenantDeployer getTenantDeployer(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/content/MimetypeMap.java b/data-model/src/main/java/org/alfresco/repo/content/MimetypeMap.java new file mode 100644 index 0000000000..54768df3ea --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/content/MimetypeMap.java @@ -0,0 +1,966 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content; + +import org.alfresco.repo.content.encoding.ContentCharsetFinder; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.FileContentReader; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.util.PropertyCheck; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.tika.config.TikaConfig; +import org.apache.tika.detect.DefaultDetector; +import org.apache.tika.detect.Detector; +import org.apache.tika.io.TikaInputStream; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.mime.MediaType; +import org.springframework.extensions.config.Config; +import org.springframework.extensions.config.ConfigElement; +import org.springframework.extensions.config.ConfigLookupContext; +import org.springframework.extensions.config.ConfigService; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeMap; + +/** + * Provides a bidirectional mapping between well-known mimetypes and the + * registered file extensions. All mimetypes and extensions are stored and + * handled as lowercase. + * + * @author Derek Hulley + */ +public class MimetypeMap implements MimetypeService +{ + + public static final String PREFIX_APPLICATION = "application/"; + + public static final String PREFIX_AUDIO = "audio/"; + + public static final String PREFIX_IMAGE = "image/"; + + public static final String PREFIX_MESSAGE = "message/"; + + public static final String PREFIX_MODEL = "model/"; + + public static final String PREFIX_MULTIPART = "multipart/"; + + public static final String PREFIX_TEXT = "text/"; + + public static final String PREFIX_VIDEO = "video/"; + + public static final String EXTENSION_BINARY = "bin"; + + public static final String MACOS_RESOURCE_FORK_FILE_NAME_PREFIX = "._"; + + public static final String MIMETYPE_MULTIPART_ALTERNATIVE = "multipart/alternative"; + + public static final String MIMETYPE_TEXT_PLAIN = "text/plain"; + + public static final String MIMETYPE_TEXT_MEDIAWIKI = "text/mediawiki"; + + public static final String MIMETYPE_TEXT_CSS = "text/css"; + + public static final String MIMETYPE_TEXT_CSV = "text/csv"; + + public static final String MIMETYPE_TEXT_JAVASCRIPT = "text/javascript"; + + public static final String MIMETYPE_XML = "text/xml"; + + public static final String MIMETYPE_HTML = "text/html"; + + public static final String MIMETYPE_XHTML = "application/xhtml+xml"; + + public static final String MIMETYPE_PDF = "application/pdf"; + + public static final String MIMETYPE_JSON = "application/json"; + + public static final String MIMETYPE_WORD = "application/msword"; + + public static final String MIMETYPE_EXCEL = "application/vnd.ms-excel"; + + public static final String MIMETYPE_BINARY = "application/octet-stream"; + + public static final String MIMETYPE_PPT = "application/vnd.ms-powerpoint"; + + public static final String MIMETYPE_APP_DWG = "application/dwg"; + + public static final String MIMETYPE_IMG_DWG = "image/vnd.dwg"; + + public static final String MIMETYPE_VIDEO_AVI = "video/x-msvideo"; + + public static final String MIMETYPE_VIDEO_QUICKTIME = "video/quicktime"; + + public static final String MIMETYPE_VIDEO_WMV = "video/x-ms-wmv"; + + public static final String MIMETYPE_VIDEO_3GP = "video/3gpp"; + + public static final String MIMETYPE_VIDEO_3GP2 = "video/3gpp2"; + + public static final String MIMETYPE_DITA = "application/dita+xml"; + + // Flash + public static final String MIMETYPE_FLASH = "application/x-shockwave-flash"; + + public static final String MIMETYPE_VIDEO_FLV = "video/x-flv"; + + public static final String MIMETYPE_APPLICATION_FLA = "application/x-fla"; + + public static final String MIMETYPE_VIDEO_MPG = "video/mpeg"; + + public static final String MIMETYPE_VIDEO_MP4 = "video/mp4"; + + public static final String MIMETYPE_IMAGE_GIF = "image/gif"; + + public static final String MIMETYPE_IMAGE_JPEG = "image/jpeg"; + + public static final String MIMETYPE_IMAGE_RGB = "image/x-rgb"; + + public static final String MIMETYPE_IMAGE_SVG = "image/svg+xml"; + + public static final String MIMETYPE_IMAGE_PNG = "image/png"; + + public static final String MIMETYPE_IMAGE_TIFF = "image/tiff"; + + public static final String MIMETYPE_IMAGE_RAW_DNG = "image/x-raw-adobe"; + + public static final String MIMETYPE_IMAGE_RAW_3FR = "image/x-raw-hasselblad"; + + public static final String MIMETYPE_IMAGE_RAW_RAF = "image/x-raw-fuji"; + + public static final String MIMETYPE_IMAGE_RAW_CR2 = "image/x-raw-canon"; + + public static final String MIMETYPE_IMAGE_RAW_K25 = "image/x-raw-kodak"; + + public static final String MIMETYPE_IMAGE_RAW_MRW = "image/x-raw-minolta"; + + public static final String MIMETYPE_IMAGE_RAW_NEF = "image/x-raw-nikon"; + + public static final String MIMETYPE_IMAGE_RAW_ORF = "image/x-raw-olympus"; + + public static final String MIMETYPE_IMAGE_RAW_PEF = "image/x-raw-pentax"; + + public static final String MIMETYPE_IMAGE_RAW_ARW = "image/x-raw-sony"; + + public static final String MIMETYPE_IMAGE_RAW_X3F = "image/x-raw-sigma"; + + public static final String MIMETYPE_IMAGE_RAW_RW2 = "image/x-raw-panasonic"; + + public static final String MIMETYPE_IMAGE_RAW_RWL = "image/x-raw-leica"; + + public static final String MIMETYPE_IMAGE_RAW_R3D = "image/x-raw-red"; + + public static final String MIMETYPE_IMAGE_DWT = "image/x-dwt"; + + public static final String MIMETYPE_APPLICATION_EPS = "application/eps"; + + public static final String MIMETYPE_APPLICATION_PS = "application/postscript"; + + public static final String MIMETYPE_JAVASCRIPT = "application/x-javascript"; + + public static final String MIMETYPE_ZIP = "application/zip"; + + public static final String MIMETYPE_OPENSEARCH_DESCRIPTION = "application/opensearchdescription+xml"; + + public static final String MIMETYPE_ATOM = "application/atom+xml"; + + public static final String MIMETYPE_RSS = "application/rss+xml"; + + public static final String MIMETYPE_RFC822 = "message/rfc822"; + + public static final String MIMETYPE_OUTLOOK_MSG = "application/vnd.ms-outlook"; + + public static final String MIMETYPE_VISIO = "application/vnd.visio"; + + public static final String MIMETYPE_VISIO_2013 = "application/vnd.visio2013"; + + // Adobe + public static final String MIMETYPE_APPLICATION_ILLUSTRATOR = "application/illustrator"; + + public static final String MIMETYPE_APPLICATION_PHOTOSHOP = "image/vnd.adobe.photoshop"; + + //Encrypted office document + public static final String MIMETYPE_ENCRYPTED_OFFICE = "application/x-tika-ooxml-protected"; + + // Open Document + public static final String MIMETYPE_OPENDOCUMENT_TEXT = "application/vnd.oasis.opendocument.text"; + + public static final String MIMETYPE_OPENDOCUMENT_TEXT_TEMPLATE = "application/vnd.oasis.opendocument.text-template"; + + public static final String MIMETYPE_OPENDOCUMENT_GRAPHICS = "application/vnd.oasis.opendocument.graphics"; + + public static final String MIMETYPE_OPENDOCUMENT_GRAPHICS_TEMPLATE = "application/vnd.oasis.opendocument.graphics-template"; + + public static final String MIMETYPE_OPENDOCUMENT_PRESENTATION = "application/vnd.oasis.opendocument.presentation"; + + public static final String MIMETYPE_OPENDOCUMENT_PRESENTATION_TEMPLATE = "application/vnd.oasis.opendocument.presentation-template"; + + public static final String MIMETYPE_OPENDOCUMENT_SPREADSHEET = "application/vnd.oasis.opendocument.spreadsheet"; + + public static final String MIMETYPE_OPENDOCUMENT_SPREADSHEET_TEMPLATE = "application/vnd.oasis.opendocument.spreadsheet-template"; + + public static final String MIMETYPE_OPENDOCUMENT_CHART = "application/vnd.oasis.opendocument.chart"; + + public static final String MIMETYPE_OPENDOCUMENT_CHART_TEMPLATE = "applicationvnd.oasis.opendocument.chart-template"; + + public static final String MIMETYPE_OPENDOCUMENT_IMAGE = "application/vnd.oasis.opendocument.image"; + + public static final String MIMETYPE_OPENDOCUMENT_IMAGE_TEMPLATE = "applicationvnd.oasis.opendocument.image-template"; + + public static final String MIMETYPE_OPENDOCUMENT_FORMULA = "application/vnd.oasis.opendocument.formula"; + + public static final String MIMETYPE_OPENDOCUMENT_FORMULA_TEMPLATE = "applicationvnd.oasis.opendocument.formula-template"; + + public static final String MIMETYPE_OPENDOCUMENT_TEXT_MASTER = "application/vnd.oasis.opendocument.text-master"; + + public static final String MIMETYPE_OPENDOCUMENT_TEXT_WEB = "application/vnd.oasis.opendocument.text-web"; + + public static final String MIMETYPE_OPENDOCUMENT_DATABASE = "application/vnd.oasis.opendocument.database"; + + // Open Office + public static final String MIMETYPE_OPENOFFICE1_WRITER = "application/vnd.sun.xml.writer"; + + public static final String MIMETYPE_OPENOFFICE1_CALC = "application/vnd.sun.xml.calc"; + + public static final String MIMETYPE_OPENOFFICE1_DRAW = "application/vnd.sun.xml.draw"; + + public static final String MIMETYPE_OPENOFFICE1_IMPRESS = "application/vnd.sun.xml.impress"; + + // Open XML + public static final String MIMETYPE_OPENXML_WORDPROCESSING = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; + public static final String MIMETYPE_OPENXML_WORDPROCESSING_MACRO = "application/vnd.ms-word.document.macroenabled.12"; + public static final String MIMETYPE_OPENXML_WORD_TEMPLATE = "application/vnd.openxmlformats-officedocument.wordprocessingml.template"; + public static final String MIMETYPE_OPENXML_WORD_TEMPLATE_MACRO = "application/vnd.ms-word.template.macroenabled.12"; + public static final String MIMETYPE_OPENXML_SPREADSHEET = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + public static final String MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE = "application/vnd.openxmlformats-officedocument.spreadsheetml.template"; + public static final String MIMETYPE_OPENXML_SPREADSHEET_MACRO = "application/vnd.ms-excel.sheet.macroenabled.12"; + public static final String MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE_MACRO = "application/vnd.ms-excel.template.macroenabled.12"; + public static final String MIMETYPE_OPENXML_SPREADSHEET_ADDIN_MACRO = "application/vnd.ms-excel.addin.macroenabled.12"; + public static final String MIMETYPE_OPENXML_SPREADSHEET_BINARY_MACRO = "application/vnd.ms-excel.sheet.binary.macroenabled.12"; + public static final String MIMETYPE_OPENXML_PRESENTATION = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; + public static final String MIMETYPE_OPENXML_PRESENTATION_MACRO = "application/vnd.ms-powerpoint.presentation.macroenabled.12"; + public static final String MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW = "application/vnd.openxmlformats-officedocument.presentationml.slideshow"; + public static final String MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW_MACRO = "application/vnd.ms-powerpoint.slideshow.macroenabled.12"; + public static final String MIMETYPE_OPENXML_PRESENTATION_TEMPLATE = "application/vnd.openxmlformats-officedocument.presentationml.template"; + public static final String MIMETYPE_OPENXML_PRESENTATION_TEMPLATE_MACRO = "application/vnd.ms-powerpoint.template.macroenabled.12"; + public static final String MIMETYPE_OPENXML_PRESENTATION_ADDIN = "application/vnd.ms-powerpoint.addin.macroenabled.12"; + public static final String MIMETYPE_OPENXML_PRESENTATION_SLIDE = "application/vnd.openxmlformats-officedocument.presentationml.slide"; + public static final String MIMETYPE_OPENXML_PRESENTATION_SLIDE_MACRO = "application/vnd.ms-powerpoint.slide.macroenabled.12"; + // Star Office + public static final String MIMETYPE_STAROFFICE5_DRAW = "application/vnd.stardivision.draw"; + + public static final String MIMETYPE_STAROFFICE5_CALC = "application/vnd.stardivision.calc"; + + public static final String MIMETYPE_STAROFFICE5_IMPRESS = "application/vnd.stardivision.impress"; + + public static final String MIMETYPE_STAROFFICE5_IMPRESS_PACKED = "application/vnd.stardivision.impress-packed"; + + public static final String MIMETYPE_STAROFFICE5_CHART = "application/vnd.stardivision.chart"; + + public static final String MIMETYPE_STAROFFICE5_WRITER = "application/vnd.stardivision.writer"; + + public static final String MIMETYPE_STAROFFICE5_WRITER_GLOBAL = "application/vnd.stardivision.writer-global"; + + public static final String MIMETYPE_STAROFFICE5_MATH = "application/vnd.stardivision.math"; + + // Apple iWorks + public static final String MIMETYPE_IWORK_KEYNOTE = "application/vnd.apple.keynote"; + + public static final String MIMETYPE_IWORK_NUMBERS = "application/vnd.apple.numbers"; + + public static final String MIMETYPE_IWORK_PAGES = "application/vnd.apple.pages"; + + //MACOS + public static final String MIMETYPE_APPLEFILE = "application/applefile"; + + // WordPerfect + public static final String MIMETYPE_WORDPERFECT = "application/wordperfect"; + + // Audio + public static final String MIMETYPE_MP3 = "audio/mpeg"; + + public static final String MIMETYPE_AUDIO_MP4 = "audio/mp4"; + + public static final String MIMETYPE_VORBIS = "audio/vorbis"; + + public static final String MIMETYPE_FLAC = "audio/x-flac"; + + // Alfresco + public static final String MIMETYPE_ACP = "application/acp"; + + private static final String CONFIG_AREA = "mimetype-map"; + + private static final String CONFIG_CONDITION = "Mimetype Map"; + + private static final String ELEMENT_MIMETYPES = "mimetypes"; + + private static final String ATTR_MIMETYPE = "mimetype"; + + private static final String ATTR_DISPLAY = "display"; + + private static final String ATTR_DEFAULT = "default"; + + private static final String ATTR_TEXT = "text"; + + private static final Log logger = LogFactory.getLog(MimetypeMap.class); + + private ConfigService configService; + + private ContentCharsetFinder contentCharsetFinder; + + private TikaConfig tikaConfig; + + private Detector detector; + + private List mimetypes; + + private Map extensionsByMimetype; + + private Map mimetypesByExtension; + + private Map displaysByMimetype; + + private Map displaysByExtension; + + private Set textMimetypes; + + /** + * Default constructor + * + * @since 2.1 + */ + public MimetypeMap() + { + } + + @Deprecated + public MimetypeMap(ConfigService configService) + { + logger.warn("MimetypeMap(ConfigService configService) has been deprecated. " + + "Use the default constructor and property 'configService'"); + this.configService = configService; + } + + public ConfigService getConfigService() + { + return configService; + } + + /** + * @param configService the config service to use to read mimetypes from + */ + public void setConfigService(ConfigService configService) + { + this.configService = configService; + } + + /** + * {@inheritDoc} + */ + public ContentCharsetFinder getContentCharsetFinder() + { + return contentCharsetFinder; + } + + /** + * Set the system default content characterset decoder + */ + public void setContentCharsetFinder(ContentCharsetFinder contentCharsetFinder) + { + this.contentCharsetFinder = contentCharsetFinder; + } + + /** + * Injects the TikaConfig to use + * + * @param tikaConfig The Tika Config to use + */ + public void setTikaConfig(TikaConfig tikaConfig) + { + this.tikaConfig = tikaConfig; + } + + /** + * Initialises the map using the configuration service provided + */ + public void init() + { + PropertyCheck.mandatory(this, "configService", configService); + PropertyCheck.mandatory(this, "contentCharsetFinder", contentCharsetFinder); + + // TikaConfig should be given, but work around it if not + if (tikaConfig == null) + { + logger.warn("TikaConfig spring parameter not supplied, using default config"); + setTikaConfig(TikaConfig.getDefaultConfig()); + } + // Create our Tika mimetype detector up-front + // We can then be sure we only have the one, so it's quick (ALF-10813) + detector = new DefaultDetector(tikaConfig.getMimeRepository()); + + // Work out the mappings + this.mimetypes = new ArrayList(40); + this.extensionsByMimetype = new HashMap(59); + this.mimetypesByExtension = new HashMap(59); + this.displaysByMimetype = new TreeMap(); + this.displaysByExtension = new HashMap(59); + this.textMimetypes = new HashSet(23); + + Config config = configService.getConfig(CONFIG_CONDITION, new ConfigLookupContext(CONFIG_AREA)); + ConfigElement mimetypesElement = config.getConfigElement(ELEMENT_MIMETYPES); + List mimetypes = mimetypesElement.getChildren(); + int count = 0; + for (ConfigElement mimetypeElement : mimetypes) + { + count++; + // add to list of mimetypes + String mimetype = mimetypeElement.getAttribute(ATTR_MIMETYPE); + if (mimetype == null || mimetype.length() == 0) + { + logger.warn("Ignoring empty mimetype " + count); + continue; + } + // we store it as lowercase + mimetype = mimetype.toLowerCase(); + boolean replacement = this.mimetypes.contains(mimetype); + if (!replacement) + { + this.mimetypes.add(mimetype); + } + // add to map of mimetype displays + String mimetypeDisplay = mimetypeElement.getAttribute(ATTR_DISPLAY); + if (mimetypeDisplay != null && mimetypeDisplay.length() > 0) + { + String prev = this.displaysByMimetype.put(mimetype, mimetypeDisplay); + if (replacement && prev != null && !mimetypeDisplay.equals(prev)) + { + logger.warn("Replacing " + mimetype + " " + ATTR_DISPLAY + " value '" + prev + "' with '" + + mimetypeDisplay + "'"); + } + } + + // Check if it is a text format + String isTextStr = mimetypeElement.getAttribute(ATTR_TEXT); + boolean isText = Boolean.parseBoolean(isTextStr) || mimetype.startsWith(PREFIX_TEXT); + boolean prevIsText = replacement ? this.textMimetypes.contains(mimetype) : !isText; + if (isText != prevIsText) + { + if (isText) + { + this.textMimetypes.add(mimetype); + } + else if (replacement) + { + this.textMimetypes.remove(mimetype); + } + if (replacement) + { + logger.warn("Replacing " + mimetype + " " + ATTR_TEXT + " value " + + (prevIsText ? "'true' with 'false'" : "'false' with 'true'")); + } + } + + // get all the extensions + List extensions = mimetypeElement.getChildren(); + for (ConfigElement extensionElement : extensions) + { + // add to map of mimetypes by extension + String extension = extensionElement.getValue(); + if (extension == null || extension.length() == 0) + { + logger.warn("Ignoring empty extension for mimetype: " + mimetype); + continue; + } + // put to lowercase + extension = extension.toLowerCase(); + this.mimetypesByExtension.put(extension, mimetype); + // add to map of extension displays + String extensionDisplay = extensionElement.getAttribute(ATTR_DISPLAY); + String prev = this.displaysByExtension.get(extension); + // if no display defined for the extension - use the mimetype's + // display + if ((prev == null) && (extensionDisplay == null || extensionDisplay.length() == 0) + && (mimetypeDisplay != null && mimetypeDisplay.length() > 0)) + { + extensionDisplay = mimetypeDisplay; + } + if (extensionDisplay != null) + { + this.displaysByExtension.put(extension, extensionDisplay); + if (prev != null && !extensionDisplay.equals(prev)) + { + logger.warn("Replacing " + mimetype + " extension " + ATTR_DISPLAY + " value '" + prev + + "' with '" + extensionDisplay + "'"); + } + } + + // add to map of extensions by mimetype if it is the default or + // first extension (prevExtension == null) + String prevExtension = this.extensionsByMimetype.get(mimetype); + String isDefaultStr = extensionElement.getAttribute(ATTR_DEFAULT); + boolean isDefault = Boolean.parseBoolean(isDefaultStr) || prevExtension == null; + if (isDefault) + { + this.extensionsByMimetype.put(mimetype, extension); + if (prevExtension != null && !extension.equals(prevExtension)) + { + logger.warn("Replacing " + mimetype + " default extension '" + prevExtension + "' with '" + + extension + "'"); + } + } + } + // check that there were extensions defined + if (extensions.size() == 0) + { + logger.warn("No extensions defined for mimetype: " + mimetype); + } + } + + // make the collections read-only + this.mimetypes = Collections.unmodifiableList(this.mimetypes); + this.extensionsByMimetype = Collections.unmodifiableMap(this.extensionsByMimetype); + this.mimetypesByExtension = Collections.unmodifiableMap(this.mimetypesByExtension); + this.displaysByMimetype = Collections.unmodifiableMap(this.displaysByMimetype); + this.displaysByExtension = Collections.unmodifiableMap(this.displaysByExtension); + } + + /** + * Get the file extension associated with the mimetype. + * + * @param mimetype a valid mimetype + * @return Returns the default extension for the mimetype. Returns the + * {@link #MIMETYPE_BINARY binary} mimetype extension. + * + * @see #MIMETYPE_BINARY + * @see #EXTENSION_BINARY + */ + public String getExtension(String mimetype) + { + String extension = extensionsByMimetype.get(mimetype); + return (extension == null ? EXTENSION_BINARY : extension); + } + + /** + * Get the mimetype for the specified extension + * + * @param extension a valid file extension + * @return Returns a valid mimetype if found, or {@link #MIMETYPE_BINARY + * binary} as default. + */ + @Override + public String getMimetype(String extension) + { + return getMimetype(extension, MIMETYPE_BINARY); + } + + /** + * Get the mimetype for the specified extension or returns the supplied default if unknown. + */ + private String getMimetype(String extension, String defaultMimetype) + { + String mimetype = null; + if (extension != null) + { + extension = extension.toLowerCase(); + if (mimetypesByExtension.containsKey(extension)) + { + mimetype = mimetypesByExtension.get(extension); + } + } + return mimetype == null ? defaultMimetype : mimetype; + } + + public Map getDisplaysByExtension() + { + return displaysByExtension; + } + + public Map getDisplaysByMimetype() + { + return displaysByMimetype; + } + + public Map getExtensionsByMimetype() + { + return extensionsByMimetype; + } + + public List getMimetypes() + { + return mimetypes; + } + + public Map getMimetypesByExtension() + { + return mimetypesByExtension; + } + + public boolean isText(String mimetype) + { + return textMimetypes.contains(mimetype); + } + + /** + * Use Apache Tika to try to guess the type of the file. + * + * @return The mimetype, or null if we can't tell. + */ + private MediaType detectType(String filename, ContentReader reader) + { +// Metadata metadata = new Metadata(); +// if (filename != null) +// { +// metadata.add(Metadata.RESOURCE_NAME_KEY, filename); +// } + TikaInputStream inp = null; + try + { + if (reader != null) + { + if (reader instanceof FileContentReader) + { + try + { + inp = TikaInputStream.get(((FileContentReader) reader).getFile()); + } + catch (FileNotFoundException e) + { + logger.warn("No backing file found for ContentReader " + e); + return null; + } + } + else + { + inp = TikaInputStream.get(reader.getContentInputStream()); + } + } + return detectType(filename, inp); + } + finally + { + if (inp != null) + { + try + { + inp.close(); + } + catch (IOException e) + { + logger.error("Error while closing TikaInputStream.", e); + } + } + } + } + + private MediaType detectType(String filename, InputStream input) + { + TikaInputStream inp = null; + if (input != null) + { + inp = TikaInputStream.get(input); + } + return detectType(filename, inp); + } + + /** + * Use Apache Tika to try to guess the type of the file. + * + * @return The mimetype, or null if we can't tell. + */ + private MediaType detectType(String filename, TikaInputStream input) + { + Metadata metadata = new Metadata(); + if (filename != null) + { + metadata.add(Metadata.RESOURCE_NAME_KEY, filename); + } + + InputStream inp = null; + if (input != null) + { + inp = TikaInputStream.get(input); + } + + MediaType type; + try + { + type = detector.detect(inp, metadata); + type = typeBasedOnDetectedTypeAndExtension(type, filename); + logger.debug(input + " detected by Tika as being " + type.toString()); + } + catch (Exception e) + { + logger.warn("Error identifying content type of problem document", e); + return null; + } + finally + { + if (inp != null) + { + try + { + inp.close(); + } + catch (Exception e) + { + // noop + } + } + } + return type; + } + + // We have a problem with .ai files, as Tika detects them as .pdf, but if we can use the filename + // we can correct that. Similar problem with .eps and .ps. + private MediaType typeBasedOnDetectedTypeAndExtension(MediaType type, String filename) + { + if (filename != null && type != null) + { + String[] detectedAndPossibleTypes = new String[] + { + MIMETYPE_PDF, MIMETYPE_APPLICATION_ILLUSTRATOR, + MIMETYPE_APPLICATION_PS, MIMETYPE_APPLICATION_EPS + }; + + for (int i=detectedAndPossibleTypes.length-1; i>=0; i-=2) + { + String detectedType = detectedAndPossibleTypes[i-1]; + if (detectedType.equals(type.toString())) + { + String possibleType = detectedAndPossibleTypes[i]; + String extension = getExtension(possibleType); + if (filename.endsWith("."+extension)) + { + type = MediaType.parse(possibleType); + break; + } + } + } + } + return type; + } + + /** + * Use Apache Tika to check if the mime type of the document really matches + * what it claims to be. This is typically used when a transformation or + * metadata extractions fails, and you want to know if someone has renamed a + * file and consequently it has the wrong mime type. + * + * @return Null if the mime type seems ok, otherwise the mime type it + * probably is + */ + public String getMimetypeIfNotMatches(ContentReader reader) + { + MediaType type = detectType(null, reader); + if (type == null) + { + // Tika doesn't know so we can't help, sorry... + return null; + } + + // Is it a good match? + if (type.toString().equals(reader.getMimetype())) { return null; } + + // Is it close? + MediaType claimed = MediaType.parse(reader.getMimetype()); + if (tikaConfig.getMediaTypeRegistry().isSpecializationOf(claimed, type) + || tikaConfig.getMediaTypeRegistry().isSpecializationOf(type, claimed)) + { + // Probably close enough + return null; + } + + // Check through known aliases of the type + SortedSet aliases = tikaConfig.getMediaTypeRegistry().getAliases(type); + for (MediaType alias : aliases) + { + String aliasType = alias.toString(); + if (aliasType.equals(claimed.toString())) + { + return null; + } + } + + // If we get here, then most likely the type is wrong + return type.toString(); + } + + /** + * Takes a guess at the mimetype based exclusively on the file extension, + * which can (and often is) wrong... + * + * @see #MIMETYPE_BINARY + */ + public String guessMimetype(String filename) + { + String mimetype = MIMETYPE_BINARY; + + // Extract the extension + if (filename != null && filename.length() > 0) + { + int index = filename.lastIndexOf('.'); + if (index > -1 && (index < filename.length() - 1)) + { + String extension = filename.substring(index + 1).toLowerCase(); + if (mimetypesByExtension.containsKey(extension)) + { + mimetype = mimetypesByExtension.get(extension); + } + } + } + return mimetype; + } + + /** + * Uses Tika to try to identify the mimetype of the file, falling back on + * {@link #guessMimetype(String)} for an extension based one if Tika can't + * help. + */ + public String guessMimetype(String filename, ContentReader reader) + { + // ALF-10813: MimetypeMap.guessMimetype consumes 30% of file upload time + // Let's only 'guess' if we need to + if (reader != null && reader.getMimetype() != null && !reader.getMimetype().equals(MimetypeMap.MIMETYPE_BINARY)) + { + // It was set to something other than the default. + // Possibly someone used this method before (like the UI does) or + // they just + // know what their files are. + return reader.getMimetype(); + } + InputStream input = (reader != null ? reader.getContentInputStream() : null); + return guessMimetype(filename, input); + } + + /** + * Uses Tika to try to identify the mimetype of the file, falling back on + * {@link #guessMimetype(String)} for an extension based one if Tika can't + * help. + */ + public String guessMimetype(String filename, InputStream input) + { + MediaType type = detectType(filename, input); + String filenameGuess = guessMimetype(filename); + + // If Tika doesn't know what the type is, or file is password protected, go with the filename one + if (type == null || MediaType.OCTET_STREAM.equals(type) || MIMETYPE_ENCRYPTED_OFFICE.equals(type.toString())) { return filenameGuess; } + + // If Tika has supplied a very generic type, go with the filename one, + // as it's probably a custom Text or XML format known only to Alfresco + if ((MediaType.TEXT_PLAIN.equals(type) || MediaType.APPLICATION_XML.equals(type)) && (! filenameGuess.equals(MIMETYPE_BINARY))) + { + return filenameGuess; + } + + // Alfresco doesn't support mimetype parameters + // Use the form of the mimetype without any + if (type.hasParameters()) + { + type = type.getBaseType(); + } + + // Not all the mimetypes we use are the Tika Canonical one. + // So, detect when this happens and use ours in preference + String tikaType = type.toString(); + if (mimetypes.contains(tikaType)) + { + // Alfresco and Tika agree! + return tikaType; + } + + // Check the aliases + SortedSet aliases = tikaConfig.getMediaTypeRegistry().getAliases(type); + for (MediaType alias : aliases) + { + String aliasType = alias.toString(); + if (mimetypes.contains(aliasType)) { return aliasType; } + } + + // If we get here, then Tika has identified something that + // Alfresco doesn't really know about. Just trust Tika on it + logger.info("Tika detected a type of " + tikaType + " for file " + filename + + " which Alfresco doesn't know about. Consider " + " adding that type to your configuration"); + return tikaType; + } + + /** + * Returns a collection of mimetypes ordered by extension. + * @param extension to restrict the collection to one entry + */ + public Collection getMimetypes(String extension) + { + Collection sourceMimetypes; + if (extension == null) + { + sourceMimetypes = getMimetypes(); + sourceMimetypes = sortMimetypesByExt(sourceMimetypes); + } + else + { + String mimetype = getMimetype(extension, null); + if (mimetype == null) + { + sourceMimetypes = Collections.emptySet(); + } + else + { + sourceMimetypes = Collections.singleton(mimetype); + } + } + return sourceMimetypes; + } + + /** + * Copies and sorts the supplied mimetypes by their file extensions + * @param mimetypes to be sorted + * @return a new List of sorted mimetypes + */ + private Collection sortMimetypesByExt(Collection mimetypes) + { + List result = new ArrayList(mimetypes); + for (int i=result.size()-1; i>= 0; i--) + { + result.set(i, getExtension(result.get(i))); + } + Collections.sort(result); + for (int i=result.size()-1; i>= 0; i--) + { + result.set(i, getMimetype(result.get(i))); + } + return result; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/content/encoding/ContentCharsetFinder.java b/data-model/src/main/java/org/alfresco/repo/content/encoding/ContentCharsetFinder.java new file mode 100644 index 0000000000..b02b755307 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/content/encoding/ContentCharsetFinder.java @@ -0,0 +1,117 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content.encoding; + +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.List; + +import org.alfresco.encoding.CharactersetFinder; +import org.alfresco.service.cmr.repository.MimetypeService; + +/** + * Utility bean to guess the charset given a stream and a mimetype. + * + * @since 2.1 + * @author Derek Hulley + */ +public class ContentCharsetFinder +{ + private Charset defaultCharset = Charset.defaultCharset(); + private MimetypeService mimetypeService; + private List charactersetFinders; + + /** + * Override the system default charset. Where the characterset cannot be determined for + * a mimetype and input stream, this mimetype will be used. The default is 'UTF-8'. + * + * @param defaultCharset the default characterset + */ + public void setDefaultCharset(String defaultCharset) + { + this.defaultCharset = Charset.forName(defaultCharset); + } + + /** + * Set the mimetype service that will help determine if a particular mimetype can be + * treated as encoded text or not. + */ + public void setMimetypeService(MimetypeService mimetypeService) + { + this.mimetypeService = mimetypeService; + } + + /** + * Set the list of characterset finder to execute, in order, for text based content. + * @param charactersetFinders a list of finders + */ + public void setCharactersetFinders(List charactersetFinders) + { + this.charactersetFinders = charactersetFinders; + } + + /** + * Gets the characterset from the stream, if the mimetype is text and the text + * has enough information to give the encoding away. Otherwise, the default + * is returned. + * + * @param is a stream that will not be affected by the call, but must + * support marking + * @param mimetype the mimetype of the stream data - null if not known + * @return returns a characterset and never null + */ + public Charset getCharset(InputStream is, String mimetype) + { + if (mimetype == null) + { + return defaultCharset; + } + // Is it text? + if (!mimetypeService.isText(mimetype)) + { + return defaultCharset; + } + // Try the finders + Charset charset = null; + for (CharactersetFinder finder : charactersetFinders) + { + charset = finder.detectCharset(is); + if (charset != null) + { + break; + } + } + // Done + if (charset == null) + { + return defaultCharset; + } + else + { + return charset; + } + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/AbstractDictionaryRegistry.java b/data-model/src/main/java/org/alfresco/repo/dictionary/AbstractDictionaryRegistry.java new file mode 100644 index 0000000000..74625eb3d2 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/AbstractDictionaryRegistry.java @@ -0,0 +1,726 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.NamespaceException; +import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * + * @author sglover + * + */ +public abstract class AbstractDictionaryRegistry implements DictionaryRegistry +{ + protected static final Log logger = LogFactory.getLog(AbstractDictionaryRegistry.class); + + protected DictionaryDAO dictionaryDAO; + private Map> uriToModels = new ConcurrentHashMap>(0); + private Map compiledModels = new ConcurrentHashMap(0); + + // namespaces + private ReadWriteLock urisCacheRWLock = new ReentrantReadWriteLock(true); + private List urisCache = new ArrayList(20); + private Map prefixesCache = new ConcurrentHashMap(0); + + public AbstractDictionaryRegistry(DictionaryDAO dictionaryDAO) + { + this.dictionaryDAO = dictionaryDAO; + } + + @Override + public void clear() + { + setCompiledModels(new HashMap()); + setUriToModels(new HashMap>()); + } + + public Map> getUriToModels() + { + Map> ret = new HashMap<>(); + ret.putAll(uriToModels); // copy + return ret; + } + + private void setUriToModels(Map> uriToModels) + { + this.uriToModels = uriToModels; + } + + @Override + public Map getCompiledModels(boolean includeInherited) + { + return compiledModels; + } + + private void setCompiledModels(Map compiledModels) + { + this.compiledModels = compiledModels; + } + + public List getModelsForUri(String uri) + { + return getModelsForUriImpl(uri); + } + + @Override + public QName putModel(CompiledModel model) + { + return putModelImpl(model); + } + + @Override + public CompiledModel getModel(QName modelName) + { + CompiledModel model = getModelImpl(modelName); + if(model == null) + { + throw new DictionaryException("d_dictionary.model.err.no_model", modelName); + } + return model; + } + + @Override + public boolean modelExists(QName modelName) + { + CompiledModel model = getModelImpl(modelName); + return model != null; + } + + @Override + public void removeModel(QName modelName) + { + removeModelImpl(modelName); + } + + protected CompiledModel removeModelImpl(QName modelName) + { + CompiledModel compiledModel = compiledModels.get(modelName); + if (compiledModel != null) + { + // Remove the namespaces from the namespace service + M2Model model = compiledModel.getM2Model(); + for (M2Namespace namespace : model.getNamespaces()) + { + prefixesCache.remove(namespace.getPrefix()); + urisCacheRWLock.writeLock().lock(); + try + { + urisCache.remove(namespace.getUri()); + } + finally + { + urisCacheRWLock.writeLock().unlock(); + } + + List models = uriToModels.get(namespace.getUri()); + if(models != null) + { + models.remove(compiledModel); + } + } + + compiledModels.remove(modelName); + } + + return compiledModel; + } + + protected CompiledModel getModelImpl(QName modelName) + { + CompiledModel model = compiledModels.get(modelName); + return model; + } + + protected List getModelsForUriImpl(String uri) + { + List models = uriToModels.get(uri); + if(models == null) + { + models = Collections.emptyList(); + } + // defensive copy + return new ArrayList(models); + } + + protected void unmapUriToModel(String uri, CompiledModel model) + { + List models = uriToModels.get(uri); + if (models != null) + { + models.remove(model); + } + } + + protected void mapUriToModel(String uri, CompiledModel model) + { + List models = uriToModels.get(uri); + if (models == null) + { + models = new ArrayList(); + uriToModels.put(uri, models); + } + if (!models.contains(model)) + { + models.add(model); + } + } + + protected QName putModelImpl(CompiledModel model) + { + QName modelName = model.getModelDefinition().getName(); + + CompiledModel previousVersion = getModelImpl(modelName); + if (previousVersion != null) + { + for (M2Namespace namespace : previousVersion.getM2Model().getNamespaces()) + { + prefixesCache.remove(namespace.getPrefix()); + + urisCacheRWLock.writeLock().lock(); + try + { + urisCache.remove(namespace.getUri()); + } + finally + { + urisCacheRWLock.writeLock().unlock(); + } + unmapUriToModel(namespace.getUri(), previousVersion); + } + + for (M2Namespace importNamespace : previousVersion.getM2Model().getImports()) + { + unmapUriToModel(importNamespace.getUri(), previousVersion); + } + } + + // Create namespace definitions for new model + M2Model m2Model = model.getM2Model(); + for (M2Namespace namespace : m2Model.getNamespaces()) + { + addURI(namespace.getUri()); + addPrefix(namespace.getPrefix(), namespace.getUri()); + mapUriToModel(namespace.getUri(), model); + } + + for (M2Namespace importNamespace : m2Model.getImports()) + { + mapUriToModel(importNamespace.getUri(), model); + } + + compiledModels.put(modelName, model); + + return modelName; + } + + @Override + public AspectDefinition getAspect(QName aspectName) + { + return getAspectImpl(aspectName); + } + + protected AspectDefinition getAspectImpl(QName aspectName) + { + AspectDefinition aspect = null; + + if(aspectName != null) + { + List models = uriToModels.get(aspectName.getNamespaceURI()); + if(models != null && models.size() > 0) + { + for (CompiledModel model : models) + { + aspect = model.getAspect(aspectName); + if(aspect != null) + { + break; + } + } + } + } + + return aspect; + } + + @Override + public AssociationDefinition getAssociation(QName assocName) + { + return getAssociationImpl(assocName); + } + + protected AssociationDefinition getAssociationImpl(QName assocName) + { + AssociationDefinition assocDef = null; + + List models = getModelsForUri(assocName.getNamespaceURI()); + if(models != null && models.size() > 0) + { + for (CompiledModel model : models) + { + assocDef = model.getAssociation(assocName); + if(assocDef != null) + { + break; + } + } + } + + return assocDef; + } + + @Override + public ClassDefinition getClass(QName className) + { + return getClassImpl(className); + } + + protected ClassDefinition getClassImpl(QName className) + { + ClassDefinition classDef = null; + + List models = getModelsForUri(className.getNamespaceURI()); + if(models != null && models.size() > 0) + { + for (CompiledModel model : models) + { + classDef = model.getClass(className); + if (classDef != null) + { + break; + } + } + } + + return classDef; + } + + @Override + public PropertyDefinition getProperty(QName propertyName) + { + return getPropertyImpl(propertyName); + } + + protected PropertyDefinition getPropertyImpl(QName propertyName) + { + PropertyDefinition propDef = null; + + List models = getModelsForUri(propertyName.getNamespaceURI()); + if(models != null && models.size() > 0) + { + for (CompiledModel model : models) + { + propDef = model.getProperty(propertyName); + if(propDef != null) + { + break; + } + } + } + + return propDef; + } + + @Override + public TypeDefinition getType(QName typeName) + { + return getTypeImpl(typeName); + } + + protected TypeDefinition getTypeImpl(QName typeName) + { + TypeDefinition typeDef = null; + + if (typeName != null) + { + List models = getModelsForUri(typeName.getNamespaceURI()); + if(models != null && models.size() > 0) + { + for (CompiledModel model : models) + { + typeDef = model.getType(typeName); + if(typeDef != null) + { + break; + } + } + } + } + + return typeDef; + } + + @Override + public ConstraintDefinition getConstraint(QName constraintQName) + { + return getConstraintImpl(constraintQName); + } + + protected ConstraintDefinition getConstraintImpl(QName constraintQName) + { + ConstraintDefinition constraintDef = null; + + List models = getModelsForUri(constraintQName.getNamespaceURI()); + if(models != null && models.size() > 0) + { + for (CompiledModel model : models) + { + constraintDef = model.getConstraint(constraintQName); + if(constraintDef != null) + { + break; + } + } + } + + return constraintDef; + } + + @Override + public DataTypeDefinition getDataType(QName typeName) + { + return getDataTypeImp(typeName); + } + + protected DataTypeDefinition getDataTypeImp(QName typeName) + { + DataTypeDefinition dataType = null; + + if (typeName != null) + { + List models = getModelsForUri(typeName.getNamespaceURI()); + if(models != null && models.size() > 0) + { + for (CompiledModel model : models) + { + dataType = model.getDataType(typeName); + if(dataType != null) + { + break; + } + } + } + } + + return dataType; + } + + @SuppressWarnings("rawtypes") + @Override + public DataTypeDefinition getDataType(Class javaClass) + { + return getDataTypeImpl(javaClass); + } + + @SuppressWarnings("rawtypes") + protected DataTypeDefinition getDataTypeImpl(Class javaClass) + { + DataTypeDefinition dataTypeDef = null; + + if (javaClass != null) + { + for (CompiledModel model : getCompiledModels(true).values()) + { + dataTypeDef = model.getDataType(javaClass); + if(dataTypeDef != null) + { + break; + } + } + } + + return dataTypeDef; + } + + protected Map getPrefixesCacheImpl() + { + return prefixesCache; + } + + @Override + public Map getPrefixesCache() + { + return getPrefixesCacheImpl(); + } + + @Override + public List getUrisCache() + { + return getUrisCacheImpl(); + } + + protected List getUrisCacheImpl() + { + urisCacheRWLock.readLock().lock(); + try + { + return new ArrayList(urisCache); + } + finally + { + urisCacheRWLock.readLock().unlock(); + } + } + + @Override + public Collection getPrefixes(String URI) + { + return getPrefixesImpl(URI); + } + + protected Collection getPrefixesImpl(String URI) + { + Collection prefixes = new ArrayList(); + + for (String key : prefixesCache.keySet()) + { + String uri = prefixesCache.get(key); + if ((uri != null) && (uri.equals(URI))) + { + prefixes.add(key); + } + } + + return prefixes; + } + + @Override + public void addURI(String uri) + { + addURIImpl(uri); + } + + protected void addURIImpl(String uri) + { + if(hasURI(uri)) + { + throw new NamespaceException("URI " + uri + " has already been defined"); + } + + urisCacheRWLock.writeLock().lock(); + try + { + urisCache.add(uri); + } + finally + { + urisCacheRWLock.writeLock().unlock(); + } + } + + @Override + public boolean hasURI(String uri) + { + urisCacheRWLock.readLock().lock(); + try + { + return urisCache.contains(uri); + } + finally + { + urisCacheRWLock.readLock().unlock(); + } + } + + @Override + public void addPrefix(String prefix, String uri) + { + addPrefixImpl(prefix, uri); + } + + @Override + public boolean hasPrefix(String prefix) + { + return prefixesCache.containsKey(prefix); + } + + protected void addPrefixImpl(String prefix, String uri) + { + urisCacheRWLock.readLock().lock(); + try + { + if(!urisCache.contains(uri)) + { + throw new NamespaceException("Namespace URI " + uri + " does not exist"); + } + if (prefixesCache.containsKey(prefix)) + { + throw new NamespaceException( + String.format("Namespace prefix '%s' is already in use for URI '%s' so cannot be registered for URI '%s'", + prefix, + prefixesCache.get(prefix), + uri)); + } + prefixesCache.put(prefix, uri); + } + finally + { + urisCacheRWLock.readLock().unlock(); + } + } + + @Override + public void removeURI(String uri) + { + removeURIImpl(uri); + } + + @Override + public void removePrefix(String prefix) + { + removePrefixImpl(prefix); + } + + protected boolean removeURIImpl(String uri) + { + urisCacheRWLock.writeLock().lock(); + try + { + return urisCache.remove(uri); + } + finally + { + urisCacheRWLock.writeLock().unlock(); + } + } + + protected boolean removePrefixImpl(String prefix) + { + return (prefixesCache.remove(prefix) != null); + } + + @Override + public Collection getTypes(boolean includeInherited) + { + Collection types = new ArrayList(100); + for (QName model : getCompiledModels(includeInherited).keySet()) + { + for(TypeDefinition typeDef : getModel(model).getTypes()) + { + types.add(typeDef.getName()); + } + } + return types; + } + + @Override + public Collection getAssociations(boolean includeInherited) + { + Collection types = new ArrayList(100); + for (QName model : getCompiledModels(includeInherited).keySet()) + { + for(AssociationDefinition assocDef : getModel(model).getAssociations()) + { + types.add(assocDef.getName()); + } + } + return types; + } + + @Override + public Collection getAspects(boolean includeInherited) + { + Collection types = new ArrayList(100); + for (QName model : getCompiledModels(includeInherited).keySet()) + { + for(AspectDefinition aspectDef : getModel(model).getAspects()) + { + types.add(aspectDef.getName()); + } + } + return types; + } + + protected abstract void initImpl(); + + @Override + public void init() + { + initImpl(); + } + + protected abstract void removeImpl(); + + @Override + public void remove() + { + uriToModels.clear(); + compiledModels.clear(); + urisCacheRWLock.writeLock().lock(); + try + { + urisCache.clear(); + } + finally + { + urisCacheRWLock.writeLock().unlock(); + } + prefixesCache.clear(); + + removeImpl(); + } + + @Override + public boolean isModelInherited(QName modelName) + { + CompiledModel model = compiledModels.get(modelName); + return (model != null); + } + + @Override + public String getNamespaceURI(String prefix) + { + String namespaceURI = null; + + if(prefix != null) + { + namespaceURI = getPrefixesCache().get(prefix); + } + + return namespaceURI; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/CompiledModel.java b/data-model/src/main/java/org/alfresco/repo/dictionary/CompiledModel.java new file mode 100644 index 0000000000..42c14fc972 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/CompiledModel.java @@ -0,0 +1,462 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import static org.alfresco.service.cmr.dictionary.DictionaryException.DuplicateDefinitionException; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.DynamicNamespacePrefixResolver; +import org.alfresco.service.namespace.NamespaceException; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * Compiled representation of a model definition. + * + * In this case, compiled means that + * a) all references between model items have been resolved + * b) inheritence of class features have been flattened + * c) overridden class features have been resolved + * + * A compiled model also represents a valid model. + * + * @author David Caruana + * + */ +public class CompiledModel implements ModelQuery +{ + + // Logger + private static final Log logger = LogFactory.getLog(DictionaryDAOImpl.class); + + private static final String ERR_COMPILE_MODEL_FAILURE = "d_dictionary.compiled_model.err.compile.failure"; + private static final String ERR_DUPLICATE_PROPERTY_TYPE = "d_dictionary.compiled_model.err.duplicate_property_type"; + private static final String ERR_DUPLICATE_TYPE = "d_dictionary.compiled_model.err.duplicate_type"; + private static final String ERR_DUPLICATE_ASPECT = "d_dictionary.compiled_model.err.duplicate_aspect"; + private static final String ERR_DUPLICATE_CONSTRAINT = "d_dictionary.compiled_model.err.duplicate_constraint"; + private static final String ERR_CYCLIC_REFERENCE = "d_dictionary.compiled_model.err.cyclic_ref"; + + private M2Model model; + private ModelDefinition modelDefinition; + private Map dataTypes = new HashMap(); + private Map classes = new HashMap(); + private Map types = new HashMap(); + private Map aspects = new HashMap(); + private Map properties = new HashMap(); + private Map associations = new HashMap(); + private Map constraints = new HashMap(); + + /** + * Construct + * + * @param model model definition + * @param dictionaryDAO dictionary DAO + * @param namespaceDAO namespace DAO + */ + /*package*/ CompiledModel(M2Model model, DictionaryDAO dictionaryDAO, NamespaceDAO namespaceDAO, boolean enableConstraintClassLoading) + { + try + { + // Phase 1: Construct model definitions from model entries + // resolving qualified names + this.model = model; + constructDefinitions(model, namespaceDAO, dictionaryDAO); + + // Phase 2: Resolve dependencies between model definitions + ModelQuery query = new DelegateModelQuery(this, dictionaryDAO); + resolveDependencies(query, namespaceDAO); + + // Phase 3: Resolve inheritance of values within class hierachy + NamespacePrefixResolver localPrefixes = createLocalPrefixResolver(model, namespaceDAO); + resolveInheritance(query, localPrefixes, constraints); + + // Phase 4: Resolve constraint dependencies + for (ConstraintDefinition def : constraints.values()) + { + ((M2ConstraintDefinition)def).resolveDependencies(query, enableConstraintClassLoading); + } + + } + catch(Exception e) + { + if (logger.isDebugEnabled()) + { + logger.debug("Failed to compile model: " + model.getName(), e); + } + throw new DictionaryException(ERR_COMPILE_MODEL_FAILURE, e, model.getName()); + } + } + + + /** + * @return the model definition + */ + public M2Model getM2Model() + { + return model; + } + + + /** + * Construct compiled definitions + * + * @param model model definition + * @param namespaceDAO namespace DAO + */ + private void constructDefinitions(M2Model model, NamespaceDAO namespaceDAO, DictionaryDAO dictionaryDAO) + { + NamespacePrefixResolver localPrefixes = createLocalPrefixResolver(model, namespaceDAO); + + // Construct Model Definition + modelDefinition = new M2ModelDefinition(model, localPrefixes, dictionaryDAO); + + // Construct Property Types + for (M2DataType propType : model.getPropertyTypes()) + { + M2DataTypeDefinition def = new M2DataTypeDefinition(modelDefinition, propType, localPrefixes); + if (dataTypes.containsKey(def.getName())) + { + throw new DuplicateDefinitionException(ERR_DUPLICATE_PROPERTY_TYPE, propType.getName()); + } + dataTypes.put(def.getName(), def); + } + + // Construct Type Definitions + for (M2Type type : model.getTypes()) + { + M2TypeDefinition def = new M2TypeDefinition(modelDefinition, type, localPrefixes, properties, associations); + if (classes.containsKey(def.getName())) + { + throw new DuplicateDefinitionException(ERR_DUPLICATE_TYPE, type.getName()); + } + classes.put(def.getName(), def); + types.put(def.getName(), def); + } + + // Construct Aspect Definitions + for (M2Aspect aspect : model.getAspects()) + { + M2AspectDefinition def = new M2AspectDefinition(modelDefinition, aspect, localPrefixes, properties, associations); + if (classes.containsKey(def.getName())) + { + throw new DuplicateDefinitionException(ERR_DUPLICATE_ASPECT, aspect.getName()); + } + classes.put(def.getName(), def); + aspects.put(def.getName(), def); + } + + // Construct Constraint Definitions + for (M2Constraint constraint : model.getConstraints()) + { + M2ConstraintDefinition def = new M2ConstraintDefinition(modelDefinition, null, constraint, localPrefixes); + QName qname = def.getName(); + if (constraints.containsKey(qname)) + { + throw new DuplicateDefinitionException(ERR_DUPLICATE_CONSTRAINT, constraint.getName()); + } + constraints.put(qname, def); + } + + } + + + /** + * Create a local namespace prefix resolver containing the namespaces defined and imported + * in the model + * + * @param model model definition + * @param namespaceDAO namespace DAO + * @return the local namespace prefix resolver + */ + private NamespacePrefixResolver createLocalPrefixResolver(M2Model model, NamespaceDAO namespaceDAO) + { + // Retrieve set of existing URIs for validation purposes + Collection uris = namespaceDAO.getURIs(); + + // Create a namespace prefix resolver based on imported and defined + // namespaces within the model + DynamicNamespacePrefixResolver prefixResolver = new DynamicNamespacePrefixResolver(null); + for (M2Namespace imported : model.getImports()) + { + String uri = imported.getUri(); + if (!uris.contains(uri)) + { + throw new NamespaceException("URI " + uri + " cannot be imported as it is not defined (with prefix " + imported.getPrefix()); + } + if(model.getNamespace(uri) != null) + { + throw new NamespaceException("URI " + uri + " cannot be imported as it is already contained in the model's namespaces"); + } + prefixResolver.registerNamespace(imported.getPrefix(), uri); + } + for (M2Namespace defined : model.getNamespaces()) + { + prefixResolver.registerNamespace(defined.getPrefix(), defined.getUri()); + } + return prefixResolver; + } + + + /** + * Resolve dependencies between model items + * + * @param query support for querying other items in model + */ + private void resolveDependencies(ModelQuery query, NamespaceDAO namespaceDAO) + { + NamespacePrefixResolver prefixResolver = createLocalPrefixResolver(model, namespaceDAO); + + for (DataTypeDefinition def : dataTypes.values()) + { + ((M2DataTypeDefinition)def).resolveDependencies(query); + } + for (ClassDefinition def : classes.values()) + { + ((M2ClassDefinition)def).resolveDependencies(query, prefixResolver, constraints); + } + } + + + /** + * Resolve class feature inheritence + * + * @param query support for querying other items in model + */ + private void resolveInheritance( + ModelQuery query, + NamespacePrefixResolver prefixResolver, + Map modelConstraints) + { + // Calculate order of class processing (root to leaf) + Map> order = new TreeMap>(); + for (ClassDefinition def : classes.values()) + { + // Calculate class depth in hierarchy + int depth = 0; + QName parentName = def.getParentName(); + Set traversedNodes = new HashSet(); + traversedNodes.add(def); + while (parentName != null) + { + ClassDefinition parentClass = getClass(parentName); + if (parentClass == null) + { + break; + } + if (traversedNodes.contains(parentClass)) + { + throw new DictionaryException(ERR_CYCLIC_REFERENCE, parentClass.getName(), model.getName()); + } + depth = depth +1; + traversedNodes.add(parentClass); + parentName = parentClass.getParentName(); + } + + // Map class to depth + List classes = order.get(depth); + if (classes == null) + { + classes = new ArrayList(); + order.put(depth, classes); + } + classes.add(def); + + if (logger.isTraceEnabled()) + { + logger.trace("Resolving inheritance: class " + def.getName() + " found at depth " + depth); + } + } + + // Resolve inheritance of each class + for (int depth = 0; depth < order.size(); depth++) + { + for (ClassDefinition def : order.get(depth)) + { + ((M2ClassDefinition)def).resolveInheritance(query, prefixResolver, modelConstraints); + } + } + } + + + /** + * @return the compiled model definition + */ + public ModelDefinition getModelDefinition() + { + return modelDefinition; + } + + + /** + * @return the compiled property types + */ + public Collection getDataTypes() + { + return dataTypes.values(); + } + + + /** + * @return the compiled types + */ + public Collection getTypes() + { + return types.values(); + } + + + /** + * @return the compiled aspects + */ + public Collection getAspects() + { + return aspects.values(); + } + + /** + * + * @return the compiled properties + */ + public Collection getProperties() + { + return properties.values(); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.impl.ModelQuery#getPropertyType(org.alfresco.repo.ref.QName) + */ + public DataTypeDefinition getDataType(QName name) + { + return dataTypes.get(name); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ModelQuery#getDataType(java.lang.Class) + */ + public DataTypeDefinition getDataType(Class javaClass) + { + for (DataTypeDefinition dataTypeDef : dataTypes.values()) + { + if (dataTypeDef.getJavaClassName().equals(javaClass.getName())) + { + return dataTypeDef; + } + } + return null; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.impl.ModelQuery#getType(org.alfresco.repo.ref.QName) + */ + public TypeDefinition getType(QName name) + { + return types.get(name); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.impl.ModelQuery#getAspect(org.alfresco.repo.ref.QName) + */ + public AspectDefinition getAspect(QName name) + { + return aspects.get(name); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.impl.ModelQuery#getClass(org.alfresco.repo.ref.QName) + */ + public ClassDefinition getClass(QName name) + { + return classes.get(name); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.impl.ModelQuery#getProperty(org.alfresco.repo.ref.QName) + */ + public PropertyDefinition getProperty(QName name) + { + return properties.get(name); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.impl.ModelQuery#getAssociation(org.alfresco.repo.ref.QName) + */ + public AssociationDefinition getAssociation(QName name) + { + return associations.get(name); + } + + /** + * @return the compiled associations + */ + public Collection getAssociations() + { + return associations.values(); + } + + /** + * @return the compiled constraints + */ + public Collection getConstraints() + { + return constraints.values(); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.impl.ModelQuery#getConstraint(QName) + */ + public ConstraintDefinition getConstraint(QName name) + { + return constraints.get(name); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/CompiledModelsCache.java b/data-model/src/main/java/org/alfresco/repo/dictionary/CompiledModelsCache.java new file mode 100644 index 0000000000..9f5d2c8394 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/CompiledModelsCache.java @@ -0,0 +1,154 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.util.cache.AbstractAsynchronouslyRefreshedCache; +import org.alfresco.util.cache.RefreshableCacheEvent; +import org.alfresco.util.cache.RefreshableCacheListener; +import org.alfresco.util.cache.RefreshableCacheRefreshedEvent; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Asynchronously refreshed cache for dictionary models. + */ +public class CompiledModelsCache extends AbstractAsynchronouslyRefreshedCache +{ + private static Log logger = LogFactory.getLog(CompiledModelsCache.class); + + private DictionaryDAOImpl dictionaryDAO; + private TenantService tenantService; + + @Override + protected DictionaryRegistry buildCache(String tenantId) + { + if (tenantId == null) + { + tenantId = tenantService.getCurrentUserDomain(); + } + + final String finalTenant = tenantId; + return AuthenticationUtil.runAs(new RunAsWork() + { + public DictionaryRegistry doWork() throws Exception + { + return dictionaryDAO.initDictionaryRegistry(finalTenant); + } + }, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantId)); + } + + /** + * @param tenantId the tenantId of cache that will be removed from live cache + * @return removed DictionaryRegistry + */ + public void remove(final String tenantId) + { + //TODO Should be reworked when ACE-2001 will be implemented + liveLock.writeLock().lock(); + try + { + DictionaryRegistry dictionaryRegistry = live.get(tenantId); + if (dictionaryRegistry != null) + { + live.remove(tenantId); + dictionaryRegistry.remove(); + + if (logger.isDebugEnabled()) + { + logger.debug("Removed dictionary register for tenant " + tenantId); + } + } + } + finally + { + liveLock.writeLock().unlock(); + } + } + + /** + * @param dictionaryDAO the dictionaryDAOImpl to set + */ + public void setDictionaryDAO(DictionaryDAOImpl dictionaryDAO) + { + this.dictionaryDAO = dictionaryDAO; + } + + /** + * @param tenantService the tenantService to set + */ + public void setTenantService(TenantService tenantService) + { + this.tenantService = tenantService; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + // RefreshableCacheListener as anonymous class since CompileModelsCache already + // implements this interface, but expects to be invoked in different circumstances. + register(new RefreshableCacheListener() + { + @Override + public void onRefreshableCacheEvent(RefreshableCacheEvent event) + { + if (logger.isDebugEnabled()) + { + logger.debug("Handling "+event.getClass().getSimpleName()+ + ", cache="+event.getCacheId()+ + ", key="+event.getKey()); + } + + if (event instanceof RefreshableCacheRefreshedEvent && + event.getCacheId().equals(getCacheId())) + { + // notify registered listeners that dictionary has been initialised (population is complete). + // Note we do that here to ensure that the dictionary registry has been added to the cache, + // so that any dependencies (like the CMIS dictionary) will use the new dictionary. + for (DictionaryListener dictionaryListener : dictionaryDAO.getDictionaryListeners()) + { + logger.debug("Calling afterDIctionaryInit ["+event.getClass().getSimpleName()+ + ", cache="+event.getCacheId()+ + ", key="+event.getKey()+ + "] on "+ + dictionaryListener.getClass().getSimpleName()); + + dictionaryListener.afterDictionaryInit(); + } + } + } + + @Override + public String getCacheId() + { + return CompiledModelsCache.this.getCacheId(); + } + }); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/CoreDictionaryRegistryImpl.java b/data-model/src/main/java/org/alfresco/repo/dictionary/CoreDictionaryRegistryImpl.java new file mode 100644 index 0000000000..aaef300f52 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/CoreDictionaryRegistryImpl.java @@ -0,0 +1,96 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.Map; + +import org.alfresco.service.namespace.QName; + +/** + * Core dictionary registry (holding core models initialised at bootstrap). + * + * @author sglover + * + */ +public class CoreDictionaryRegistryImpl extends AbstractDictionaryRegistry +{ + public CoreDictionaryRegistryImpl(DictionaryDAO dictionaryDAO) + { + super(dictionaryDAO); + } + + @Override + public String getTenantDomain() + { + return null; + } + + @Override + protected void initImpl() + { + long startTime = System.currentTimeMillis(); + + // populate the dictionary based on registered sources (only for core registry) + for (DictionaryListener dictionaryDeployer : dictionaryDAO.getDictionaryListeners()) + { + dictionaryDeployer.onDictionaryInit(); + } + + // Done + if (logger.isInfoEnabled()) + { + Map models = getCompiledModels(false); + logger.info("Init core dictionary: model count = "+(models != null ? models.size() : 0) + +" in "+(System.currentTimeMillis()-startTime)+" msecs ["+Thread.currentThread()+"]"); + } + } + + @Override + public void remove() + { + for(DictionaryListener listener : dictionaryDAO.getDictionaryListeners()) + { + listener.afterDictionaryDestroy(); + } + } + + @Override + protected QName putModelImpl(CompiledModel model) + { + // TODO disallow model overrides for the core dictionary + QName qname = super.putModelImpl(model); + return qname; + } + + @Override + public void removeImpl() + { + for(DictionaryListener listener : dictionaryDAO.getDictionaryListeners()) + { + listener.afterDictionaryDestroy(); + } + } +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/CustomModelDefinitionImpl.java b/data-model/src/main/java/org/alfresco/repo/dictionary/CustomModelDefinitionImpl.java new file mode 100644 index 0000000000..7b86ed3356 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/CustomModelDefinitionImpl.java @@ -0,0 +1,215 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.repo.dictionary; + +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.CustomModelDefinition; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.NamespaceDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.QName; + +/** + * Read-only definition of a Custom Model + * + * @author Jamal Kaabi-Mofrad + */ +public class CustomModelDefinitionImpl implements CustomModelDefinition +{ + private final ModelDefinition m2ModelDefinition; + private final boolean active; + private final MessageLookup messageLookup; + private final Collection typeDefinitions; + private final Collection aspectDefinitions; + private final Collection modelDefinedConstraints; + + /* package */CustomModelDefinitionImpl(CompiledModel compiledModel, boolean active, MessageLookup messageLookup) + { + this.m2ModelDefinition = compiledModel.getModelDefinition(); + this.active = active; + this.messageLookup = messageLookup; + // compiledModel.getTypes(), getAspects and getConstraints are never null + this.typeDefinitions = new ArrayList<>(compiledModel.getTypes()); + this.aspectDefinitions = new ArrayList<>(compiledModel.getAspects()); + this.modelDefinedConstraints = removeInlineConstraints(compiledModel); + } + + /** + * Removes the inline constraints (i.e. defined within the property) from + * all constraints. The result will be constraints that have been defined + * within the model (Top level) itself. + * + * @param compiledModel the compiled model + * @return list of model defined constraints + */ + public static List removeInlineConstraints(CompiledModel compiledModel) + { + List modelConstraints = new ArrayList<>(); + + Set propertyConstraints = new HashSet<>(); + for(PropertyDefinition propDef : compiledModel.getProperties()) + { + if (propDef.getConstraints().size() > 0) + { + for (ConstraintDefinition propConst : propDef.getConstraints()) + { + propertyConstraints.add(propConst.getName()); + } + } + } + + for (ConstraintDefinition constraint : compiledModel.getConstraints()) + { + if (!propertyConstraints.contains(constraint.getName())) + { + modelConstraints.add(constraint); + } + } + + return modelConstraints; + } + + @Override + public String getDescription() + { + return getDescription(messageLookup); + } + + @Override + public boolean isActive() + { + return this.active; + } + + @Override + public String getAnalyserResourceBundleName() + { + return m2ModelDefinition.getAnalyserResourceBundleName(); + } + + @Override + public String getAuthor() + { + return m2ModelDefinition.getAuthor(); + } + + @Override + public long getChecksum(XMLBindingType xmlbindingtype) + { + return m2ModelDefinition.getChecksum(xmlbindingtype); + } + + @Override + public String getDescription(MessageLookup messagelookup) + { + return m2ModelDefinition.getDescription(messagelookup); + } + + @Override + public DictionaryDAO getDictionaryDAO() + { + return m2ModelDefinition.getDictionaryDAO(); + } + + @Override + public Collection getImportedNamespaces() + { + return m2ModelDefinition.getImportedNamespaces(); + } + + @Override + public QName getName() + { + return m2ModelDefinition.getName(); + } + + @Override + public Collection getNamespaces() + { + return m2ModelDefinition.getNamespaces(); + } + + @Override + public Date getPublishedDate() + { + return m2ModelDefinition.getPublishedDate(); + } + + @Override + public String getVersion() + { + return m2ModelDefinition.getVersion(); + } + + @Override + public boolean isNamespaceDefined(String uri) + { + return m2ModelDefinition.isNamespaceDefined(uri); + } + + @Override + public boolean isNamespaceImported(String uri) + { + return m2ModelDefinition.isNamespaceImported(uri); + } + + @Override + public void toXML(XMLBindingType xmlbindingtype, OutputStream xml) + { + m2ModelDefinition.toXML(xmlbindingtype, xml); + } + + @Override + public Collection getTypeDefinitions() + { + return Collections.unmodifiableCollection(typeDefinitions); + } + + @Override + public Collection getAspectDefinitions() + { + return Collections.unmodifiableCollection(aspectDefinitions); + } + + @Override + public Collection getModelDefinedConstraints() + { + return Collections.unmodifiableCollection(modelDefinedConstraints); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/CustomModelsInfo.java b/data-model/src/main/java/org/alfresco/repo/dictionary/CustomModelsInfo.java new file mode 100644 index 0000000000..63ecd594b8 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/CustomModelsInfo.java @@ -0,0 +1,69 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.repo.dictionary; + +/** + * A simple POJO to encapsulate the custom models' statistics information. + * + * @author Jamal Kaabi-Mofrad + */ +public class CustomModelsInfo +{ + private int numberOfActiveModels; + private int numberOfActiveTypes; + private int numberOfActiveAspects; + + public int getNumberOfActiveModels() + { + return this.numberOfActiveModels; + } + + public void setNumberOfActiveModels(int numberOfActiveModels) + { + this.numberOfActiveModels = numberOfActiveModels; + } + + public int getNumberOfActiveTypes() + { + return this.numberOfActiveTypes; + } + + public void setNumberOfActiveTypes(int numberOfActiveTypes) + { + this.numberOfActiveTypes = numberOfActiveTypes; + } + + public int getNumberOfActiveAspects() + { + return this.numberOfActiveAspects; + } + + public void setNumberOfActiveAspects(int numberOfActiveAspects) + { + this.numberOfActiveAspects = numberOfActiveAspects; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/DelegateModelQuery.java b/data-model/src/main/java/org/alfresco/repo/dictionary/DelegateModelQuery.java new file mode 100644 index 0000000000..3f1fd273a6 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/DelegateModelQuery.java @@ -0,0 +1,173 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.QName; + +/** + * Model query that delegates its search if itself cannot find the model + * item required. + * + * @author David Caruana + * + */ +/*package*/ class DelegateModelQuery implements ModelQuery +{ + + private ModelQuery query; + private ModelQuery delegate; + + + /** + * Construct + * + * @param query ModelQuery + * @param delegate ModelQuery + */ + /*package*/ DelegateModelQuery(ModelQuery query, ModelQuery delegate) + { + this.query = query; + this.delegate = delegate; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.impl.ModelQuery#getPropertyType(org.alfresco.repo.ref.QName) + */ + public DataTypeDefinition getDataType(QName name) + { + DataTypeDefinition def = query.getDataType(name); + if (def == null) + { + def = delegate.getDataType(name); + } + return def; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ModelQuery#getDataType(java.lang.Class) + */ + public DataTypeDefinition getDataType(Class javaClass) + { + DataTypeDefinition def = query.getDataType(javaClass); + if (def == null) + { + def = delegate.getDataType(javaClass); + } + return def; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.impl.ModelQuery#getType(org.alfresco.repo.ref.QName) + */ + public TypeDefinition getType(QName name) + { + TypeDefinition def = query.getType(name); + if (def == null) + { + def = delegate.getType(name); + } + return def; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.impl.ModelQuery#getAspect(org.alfresco.repo.ref.QName) + */ + public AspectDefinition getAspect(QName name) + { + AspectDefinition def = query.getAspect(name); + if (def == null) + { + def = delegate.getAspect(name); + } + return def; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.impl.ModelQuery#getClass(org.alfresco.repo.ref.QName) + */ + public ClassDefinition getClass(QName name) + { + ClassDefinition def = query.getClass(name); + if (def == null) + { + def = delegate.getClass(name); + } + return def; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.impl.ModelQuery#getProperty(org.alfresco.repo.ref.QName) + */ + public PropertyDefinition getProperty(QName name) + { + PropertyDefinition def = query.getProperty(name); + if (def == null) + { + def = delegate.getProperty(name); + } + return def; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.impl.ModelQuery#getAssociation(org.alfresco.repo.ref.QName) + */ + public AssociationDefinition getAssociation(QName name) + { + AssociationDefinition def = query.getAssociation(name); + if (def == null) + { + def = delegate.getAssociation(name); + } + return def; + } + + /* (non-Javadoc) + * @see ModelQuery#getConstraint(QName) + */ + public ConstraintDefinition getConstraint(QName name) + { + ConstraintDefinition def = query.getConstraint(name); + if (def == null) + { + def = delegate.getConstraint(name); + } + return def; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryBootstrap.java b/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryBootstrap.java new file mode 100644 index 0000000000..256eefbb2e --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryBootstrap.java @@ -0,0 +1,232 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Properties; + +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.surf.util.I18NUtil; + + +/** + * Bootstrap Dictionary DAO with pre-defined models & message resources (from classpath) + * + * @author David Caruana, janv + * + */ +public class DictionaryBootstrap implements DictionaryListener +{ + // The list of models to bootstrap with + private List models = new ArrayList(); + + // The list of model resource bundles to bootstrap with + private List resourceBundles = new ArrayList(); + + // Dictionary DAO + private DictionaryDAO dictionaryDAO = null; + + // Tenant Service + private TenantService tenantService; + + private Properties globalProperties; + + // Logger + private static Log logger = LogFactory.getLog(DictionaryBootstrap.class); + + + /** + * Sets the Dictionary DAO + * + * @param dictionaryDAO DictionaryDAO + */ + public void setDictionaryDAO(DictionaryDAO dictionaryDAO) + { + this.dictionaryDAO = dictionaryDAO; + } + + /** + * Sets the Tenant Service + * + * @param tenantService TenantService + */ + public void setTenantService(TenantService tenantService) + { + this.tenantService = tenantService; + } + + /** + * Sets the global properties + * + * @param globalProperties + */ + public void setGlobalProperties(Properties globalProperties) + { + this.globalProperties = globalProperties; + } + + /** + * Sets the initial list of models to bootstrap with + * + * @param modelResources the model names + */ + public void setModels(List modelResources) + { + this.models = modelResources; + } + + /** + * Sets the initial list of models to bootstrap with + * + * @param labels the labels + */ + public void setLabels(List labels) + { + this.resourceBundles = labels; + } + + /** + * Bootstrap the Dictionary - register and populate + * + */ + public void bootstrap() + { + onDictionaryInit(); + initStaticMessages(); + + register(); + } + + /** + * Register with the Dictionary + */ + private void register() + { + dictionaryDAO.registerListener(this); + } + + /* + * (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryListener#onInit() + */ + public void onDictionaryInit() + { + long startTime = System.currentTimeMillis(); + + if (logger.isTraceEnabled()) + { + logger.trace("onDictionaryInit: ["+Thread.currentThread()+"]"); + } + + // note: on first bootstrap will init empty dictionary + Collection modelsBefore = dictionaryDAO.getModels(true); // note: on first bootstrap will init empty dictionary + int modelsBeforeCnt = (modelsBefore != null ? modelsBefore.size() : 0); + + if ((tenantService == null) || (! tenantService.isTenantUser())) + { + // register models + for (String bootstrapModel : models) + { + InputStream modelStream = getClass().getClassLoader().getResourceAsStream(bootstrapModel); + if (modelStream == null) + { + throw new DictionaryException("d_dictionary.bootstrap.model_not_found", bootstrapModel); + } + try + { + M2Model model = M2Model.createModel(modelStream); + model.setConfigProperties(globalProperties); + + if (logger.isDebugEnabled()) + { + logger.debug("Loading model: "+model.getName()+" (from "+bootstrapModel+")"); + } + + dictionaryDAO.putModel(model); + } + catch(DictionaryException e) + { + throw new DictionaryException("d_dictionary.bootstrap.model_not_imported", e, bootstrapModel); + } + finally + { + try + { + modelStream.close(); + } + catch (IOException ioe) + { + logger.warn("Failed to close model input stream for '"+bootstrapModel+"': "+ioe); + } + } + } + + Collection modelsAfter = dictionaryDAO.getModels(true); + int modelsAfterCnt = (modelsAfter != null ? modelsAfter.size() : 0); + + if (logger.isDebugEnabled()) + { + logger.debug("Model count: before="+modelsBeforeCnt+", load="+models.size()+", after="+modelsAfterCnt+" in "+(System.currentTimeMillis()-startTime)+" msecs ["+Thread.currentThread()+"]"); + } + } + } + + /* + * (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryListener#afterInit() + */ + public void afterDictionaryInit() + { + } + + /* + * (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryListener#onDictionaryDestroy() + */ + public void afterDictionaryDestroy() + { + } + + /** + * Register the static resource bundles + */ + private void initStaticMessages() + { + // register messages + for (String resourceBundle : resourceBundles) + { + I18NUtil.registerResourceBundle(resourceBundle); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryComponent.java b/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryComponent.java new file mode 100644 index 0000000000..3f1e3dca86 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryComponent.java @@ -0,0 +1,548 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.alfresco.repo.tenant.TenantDeployer; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.QName; +import org.springframework.extensions.surf.util.ParameterCheck; + +/** + * Data Dictionary Service Implementation + * + * @author David Caruana + * @author sglover + */ +public class DictionaryComponent implements DictionaryService, TenantDeployer +{ + private DictionaryDAO dictionaryDAO; + private MessageLookup messageLookup; + + // TODO: Check passed arguments are valid + + /** + * Sets the Meta Model DAO + * + * @param dictionaryDAO dictionary DAO + */ + public void setDictionaryDAO(DictionaryDAO dictionaryDAO) + { + this.dictionaryDAO = dictionaryDAO; + } + + /** + * Sets the message lookup service + * + * @param messageLookup + * the message lookup service + */ + public void setMessageLookup(MessageLookup messageLookup) + { + this.messageLookup = messageLookup; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getAllModels() + */ + public Collection getAllModels() + { + return getAllModels(true); + } + + public Collection getAllModels(boolean includeInherited) + { + return dictionaryDAO.getModels(includeInherited); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getModel(org.alfresco.repo.ref.QName) + */ + public ModelDefinition getModel(QName model) + { + return dictionaryDAO.getModel(model); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getAllPropertyTypes() + */ + public Collection getAllDataTypes() + { + Collection propertyTypes = new ArrayList(); + for (QName model : getAllModels()) + { + propertyTypes.addAll(getDataTypes(model)); + } + return propertyTypes; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getPropertyTypes(org.alfresco.repo.ref.QName) + */ + public Collection getDataTypes(QName model) + { + Collection propertyTypes = dictionaryDAO.getDataTypes(model); + Collection qnames = new ArrayList(propertyTypes.size()); + for (DataTypeDefinition def : propertyTypes) + { + qnames.add(def.getName()); + } + return qnames; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getAllTypes() + */ + public Collection getAllTypes() + { + return getAllTypes(true); + } + + public Collection getAllTypes(boolean includeInherited) + { + return dictionaryDAO.getTypes(includeInherited); + } + + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.DictionaryService#getSubTypes(org.alfresco.service.namespace.QName, boolean) + */ + public Collection getSubTypes(QName superType, boolean follow) + { + return dictionaryDAO.getSubTypes(superType, follow); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getTypes(org.alfresco.repo.ref.QName) + */ + public Collection getTypes(QName model) + { + Collection types = dictionaryDAO.getTypes(model); + Collection qnames = new ArrayList(types.size()); + for (TypeDefinition def : types) + { + qnames.add(def.getName()); + } + return qnames; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getAllAspects() + */ + public Collection getAllAspects() + { + return getAllAspects(true); + } + + public Collection getAllAspects(boolean includeInherited) + { + return dictionaryDAO.getAspects(includeInherited); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getAllAssociations() + */ + public Collection getAllAssociations() + { + return getAllAssociations(true); + } + + public Collection getAllAssociations(boolean includeInherited) + { + return dictionaryDAO.getAssociations(includeInherited); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.DictionaryService#getSubAspects(org.alfresco.service.namespace.QName, boolean) + */ + public Collection getSubAspects(QName superAspect, boolean follow) + { + return dictionaryDAO.getSubAspects(superAspect, follow); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getAspects(org.alfresco.repo.ref.QName) + */ + public Collection getAspects(QName model) + { + Collection aspects = dictionaryDAO.getAspects(model); + Collection qnames = new ArrayList(aspects.size()); + for (AspectDefinition def : aspects) + { + qnames.add(def.getName()); + } + return qnames; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getAssociations(org.alfresco.repo.ref.QName) + */ + public Collection getAssociations(QName model) + { + Collection associations = dictionaryDAO.getAssociations(model); + Collection qnames = new ArrayList(associations.size()); + for (AssociationDefinition def : associations) + { + qnames.add(def.getName()); + } + return qnames; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#isSubClass(org.alfresco.repo.ref.QName, org.alfresco.repo.ref.QName) + */ + public boolean isSubClass(QName className, QName ofClassName) + { + // Validate arguments + ParameterCheck.mandatory("className", className); + ParameterCheck.mandatory("ofClassName", ofClassName); + ClassDefinition classDef = getClass(className); + if (classDef == null) + { + return false; + } + ClassDefinition ofClassDef = getClass(ofClassName); + if (ofClassDef == null) + { + return false; + } + + // Only check if both ends are either a type or an aspect + boolean subClassOf = false; + if (classDef.isAspect() == ofClassDef.isAspect()) + { + while (classDef != null) + { + if (classDef.equals(ofClassDef)) + { + subClassOf = true; + break; + } + + // No match yet, so go to parent class + QName parentClassName = classDef.getParentName(); + classDef = (parentClassName == null) ? null : getClass(parentClassName); + } + } + return subClassOf; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getPropertyType(org.alfresco.repo.ref.QName) + */ + public DataTypeDefinition getDataType(QName name) + { + return dictionaryDAO.getDataType(name); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.DictionaryService#getDataType(java.lang.Class) + */ + public DataTypeDefinition getDataType(Class javaClass) + { + return dictionaryDAO.getDataType(javaClass); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getType(org.alfresco.repo.ref.QName) + */ + public TypeDefinition getType(QName name) + { + return dictionaryDAO.getType(name); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getAspect(org.alfresco.repo.ref.QName) + */ + public AspectDefinition getAspect(QName name) + { + return dictionaryDAO.getAspect(name); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getClass(org.alfresco.repo.ref.QName) + */ + public ClassDefinition getClass(QName name) + { + return dictionaryDAO.getClass(name); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getAnonymousType(org.alfresco.repo.ref.QName, java.util.Collection) + */ + public TypeDefinition getAnonymousType(QName type, Collection aspects) + { + return dictionaryDAO.getAnonymousType(type, aspects); + } + + /** + * + * {@inheritDoc} + */ + public TypeDefinition getAnonymousType(QName name) + { + TypeDefinition typeDef = getType(name); + List aspects = typeDef.getDefaultAspects(true); + List aspectNames = new ArrayList(aspects.size()); + getMandatoryAspects(typeDef, aspectNames); + return getAnonymousType(typeDef.getName(), aspectNames); + } + + /** + * Gets a flattened list of all mandatory aspects for a given class + * + * @param classDef the class + * @param aspects a list to hold the mandatory aspects + */ + private void getMandatoryAspects(ClassDefinition classDef, List aspects) + { + for (AspectDefinition aspect : classDef.getDefaultAspects()) + { + QName aspectName = aspect.getName(); + if (!aspects.contains(aspectName)) + { + aspects.add(aspect.getName()); + getMandatoryAspects(aspect, aspects); + } + } + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getProperty(org.alfresco.repo.ref.QName, org.alfresco.repo.ref.QName) + */ + public PropertyDefinition getProperty(QName className, QName propertyName) + { + PropertyDefinition propDef = null; + ClassDefinition classDef = dictionaryDAO.getClass(className); + if (classDef != null) + { + Map propDefs = classDef.getProperties(); + propDef = propDefs.get(propertyName); + } + return propDef; + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.DictionaryService#getPropertyDefs(org.alfresco.service.namespace.QName) + */ + public Map getPropertyDefs(QName className) + { + ClassDefinition classDef = dictionaryDAO.getClass(className); + if (classDef != null) + { + return classDef.getProperties(); + } + return null; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getProperty(org.alfresco.repo.ref.QName) + */ + public PropertyDefinition getProperty(QName propertyName) + { + return dictionaryDAO.getProperty(propertyName); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.DictionaryService#getAssociation(org.alfresco.repo.ref.QName) + */ + public AssociationDefinition getAssociation(QName associationName) + { + return dictionaryDAO.getAssociation(associationName); + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.DictionaryService#getAllProperties(org.alfresco.service.namespace.QName) + */ + public Collection getAllProperties(QName dataType) + { + Collection aspects = new HashSet(64); + for (QName model : getAllModels()) + { + aspects.addAll(getProperties(model, dataType)); + } + return aspects; + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.DictionaryService#getAllProperties(org.alfresco.service.namespace.QName, org.alfresco.service.namespace.QName) + */ + public Collection getProperties(QName model, QName dataType) + { + Collection propDefs = dictionaryDAO.getProperties(model, dataType); + HashSet props = new HashSet(propDefs.size()); + for(PropertyDefinition def : propDefs) + { + props.add(def.getName()); + } + return props; + + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.DictionaryService#getProperties(org.alfresco.service.namespace.QName) + */ + public Collection getProperties(QName model) + { + Collection propDefs = dictionaryDAO.getProperties(model); + HashSet props = new HashSet(propDefs.size()); + for(PropertyDefinition def : propDefs) + { + props.add(def.getName()); + } + return props; + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.DictionaryService#getConstraint(org.alfresco.service.namespace.QName) + */ + public ConstraintDefinition getConstraint(QName constraintQName) + { + return dictionaryDAO.getConstraint(constraintQName); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.DictionaryService#getConstraints(org.alfresco.service.namespace.QName) + */ + public Collection getConstraints(QName model) + { + return dictionaryDAO.getConstraints(model); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.DictionaryService#getConstraints(org.alfresco.service.namespace.QName, boolean) + */ + public Collection getConstraints(QName model, boolean referenceableDefsOnly) + { + return dictionaryDAO.getConstraints(model, referenceableDefsOnly); + } + + public void init() + { + dictionaryDAO.init(); + } + + public void destroy() + { + dictionaryDAO.destroy(); + } + + public void onEnableTenant() + { + dictionaryDAO.reset(); // to initialise empty dictionary and re-populate + } + + public void onDisableTenant() + { + dictionaryDAO.destroy(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.i18n.MessageLookup#getMessage(java.lang.String) + */ + @Override + public String getMessage(String messageKey) + { + return messageLookup.getMessage(messageKey); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.i18n.MessageLookup#getMessage(java.lang.String, java.util.Locale) + */ + @Override + public String getMessage(String messageKey, Locale locale) + { + return messageLookup.getMessage(messageKey, locale); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.i18n.MessageLookup#getMessage(java.lang.String, java.lang.Object[]) + */ + @Override + public String getMessage(String messageKey, Object... params) + { + return messageLookup.getMessage(messageKey, params); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.i18n.MessageLookup#getMessage(java.lang.String, java.util.Locale, java.lang.Object[]) + */ + @Override + public String getMessage(String messageKey, Locale locale, Object... params) + { + return messageLookup.getMessage(messageKey, locale, params); + } + + @Override + public ModelDefinition getModelByNamespaceUri(String uri) + { + for(QName modelQname : dictionaryDAO.getModels()) + { + if(modelQname.getNamespaceURI().equals(uri)) + { + return getModel(modelQname); + } + } + return null; + } + +// @Override +// public Collection getCoreTypes() +// { +// return dictionaryDAO.getCoreTypes(); +// } +// +// @Override +// public Collection getCoreAspects() +// { +// return dictionaryDAO.getCoreAspects(); +// } +// +// @Override +// public Collection getCoreAssociations() +// { +// return dictionaryDAO.getCoreAssociations(); +// } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryDAO.java b/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryDAO.java new file mode 100644 index 0000000000..34cb5d7fae --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryDAO.java @@ -0,0 +1,297 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.Collection; +import java.util.List; + +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.NamespaceDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.QName; + +/** + * Dictionary Data Access + * + * @author David Caruana, sglover + */ +public interface DictionaryDAO extends ModelQuery +{ + /** + * get DictionaryListener registered by calls to registerListener + * + * @see org.alfresco.repo.dictionary.DictionaryListener + * @return read only list of dictionary listeners + */ + List getDictionaryListeners(); + + DictionaryRegistry getDictionaryRegistry(String tenantDomain); + + boolean isContextRefreshed(); + + /** + * @return the models known by the dictionary + */ + /** + * @return the models known by the dictionary + */ + Collection getModels(); + + Collection getModels(boolean includeInherited); + + Collection getTypes(boolean includeInherited); + + Collection getAssociations(boolean includeInherited); + + Collection getAspects(boolean includeInherited); + + /** + * @param name + * the model to retrieve + * @return the named model definition + */ + ModelDefinition getModel(QName name); + + /** + * @param model + * the model to retrieve property types for + * @return the property types of the model + */ + Collection getDataTypes(QName model); + + /** + * @param model + * the model to retrieve types for + * @return the types of the model + */ + Collection getTypes(QName model); + + /** + * @param superType QName + * @param follow + * true => follow up the super-class hierarchy, false => + * immediate sub types only + */ + Collection getSubTypes(QName superType, boolean follow); + + /** + * @param model + * the model to retrieve aspects for + * @return the aspects of the model + */ + Collection getAspects(QName model); + + /** + * @param model + * the model to retrieve associations for + * @return the associations of the model + */ + Collection getAssociations(QName model); + + /** + * @param superAspect QName + * @param follow + * true => follow up the super-class hierarchy, false => + * immediate sub aspects only + */ + Collection getSubAspects(QName superAspect, boolean follow); + + /** + * @param model + * the model for which to get properties for + * @return the properties of the model + */ + Collection getProperties(QName model); + + /** + * Construct an anonymous type that combines a primary type definition and + * and one or more aspects + * + * @param type + * the primary type + * @param aspects + * the aspects to combine + * @return the anonymous type definition + */ + TypeDefinition getAnonymousType(QName type, Collection aspects); + + /** + * Adds a model to the dictionary. The model is compiled and validated. + * + * @param model + * the model to add + * @return QName name of model + */ + QName putModel(M2Model model); + + // QName putCustomModel(M2Model model); + + /** + * Adds a model to the dictionary. The model is compiled and validated. + * Constraints are not loaded. + * + * This method should only be used to load models where the enforcement of + * constraints is never required. For example, SOLR read only use of the + * index where contraints are not required and thier definitions may not be + * available. + * + * @param model + * the model to add + * @return QName name of model + */ + QName putModelIgnoringConstraints(M2Model model); + + /** + * Removes a model from the dictionary. The types and aspect in the model + * will no longer be available. + * + * @param model + * the qname of the model to remove + */ + void removeModel(QName model); + + /** + * Get all properties for the model and that are of the given data type. If + * dataType is null then the all properties will be returned. + * + * @param modelName + * the name of the model + * @param dataType + * null to get all properties + * @return the properties associated with the model + */ + Collection getProperties(QName modelName, QName dataType); + + /** + * Get all properties for all models of the given data type. + * + * @param dataType QName + */ + Collection getPropertiesOfDataType(QName dataType); + + /** + * @param modelName + * the model to retrieve namespaces for + * @return the namespaces of the model + */ + Collection getNamespaces(QName modelName); + + /** + * @param model + * the model to retrieve constraint defs (including property + * constaint refs) + * @return the constraints of the model + */ + Collection getConstraints(QName model); + + /** + * @param model + * the model to retrieve constraint defs (optionally only + * referenceable constraints) + * @return the constraints of the model + */ + Collection getConstraints(QName model, + boolean referenceableDefsOnly); + + /** + * Return diffs between input model and model in the Dictionary. + * + * If the input model does not exist in the Dictionary then no diffs will be + * returned. + * + * @param model M2Model + * @return model diffs (if any) + */ + List diffModel(M2Model model); + + List diffModelIgnoringConstraints(M2Model model); + + /** + * Register listener with the Dictionary + *

+ * This method is deprecated, use {@link #registerListener(DictionaryListener dictionaryListener)} instead. + *

+ * @param dictionaryListener + */ + @Deprecated + void register(DictionaryListener dictionaryListener); + + /** + * + * Register listener with the Dictionary + * + * @param dictionaryListener DictionaryListener + */ + void registerListener(DictionaryListener dictionaryListener); + + /** + * Reset the Dictionary for the current tenant. + * The current dictionary will be discarded and reloaded before the method returns + * i.e. upon return the dictionary will be current. + */ + void reset(); + + /** + * Initialise a reload of the dictionary for the current tenant. The current version of + * the dictionary will be accessible during this call, however it will only return once + * the dictionary has undergone a reload for the current tenant. + */ + void init(); + + /** + * Destroy the Dictionary. After this call, there will be no dictionary available for the current + * tenant; reloading will be done lazily as required. + *

+ * WARNING: This method can cause 'stutter' on user threads as they wait for + * the dictionary to reload. It is safer to call {@link #init()}, which will also rebuild the + * dictionary but will not destroy the old one, thereby allowing other threads to continue + * operating. + */ + void destroy(); + + // MT-specific + boolean isModelInherited(QName name); + + /** + * @return String + */ + String getDefaultAnalyserResourceBundleName(); + + /** + * @return ClassLoader + */ + ClassLoader getResourceClassLoader(); + + /** + * @param resourceClassLoader ClassLoader + */ + void setResourceClassLoader(ClassLoader resourceClassLoader); +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java b/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java new file mode 100644 index 0000000000..e29ce1965d --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryDAOImpl.java @@ -0,0 +1,1047 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.NamespaceDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; + +/** + * Default implementation of the Dictionary. + * + * @author David Caruana, janv, sglover + * + */ +// TODO deal with destroy of core dictionary registry i.e. do we remove all +// tenant dictionary registries too? +public class DictionaryDAOImpl implements DictionaryDAO, NamespaceDAO, + ApplicationListener +{ + // Tenant Service + private TenantService tenantService; + + // used to reset the cache + private ThreadLocal> dictionaryRegistryThreadLocal = new ThreadLocal>(); + + // Internal cache (clusterable) + private CompiledModelsCache dictionaryRegistryCache; + + // Static list of registered dictionary listeners + private List dictionaryListeners = new ArrayList(); + private ReadWriteLock dictionaryListenersLock = new ReentrantReadWriteLock(); + + // Logger + private static Log logger = LogFactory.getLog(DictionaryDAO.class); + + private String defaultAnalyserResourceBundleName; + + private ClassLoader resourceClassLoader; + + // inject dependencies + + public void setTenantService(TenantService tenantService) + { + this.tenantService = tenantService; + } + + public void setDictionaryRegistryCache( + CompiledModelsCache dictionaryRegistryCache) + { + this.dictionaryRegistryCache = dictionaryRegistryCache; + } + + @Override + public String getDefaultAnalyserResourceBundleName() + { + return defaultAnalyserResourceBundleName; + } + + public void setDefaultAnalyserResourceBundleName( + String defaultAnalyserResourceBundleName) + { + this.defaultAnalyserResourceBundleName = defaultAnalyserResourceBundleName; + } + + /** + * Construct + * + */ + public DictionaryDAOImpl() + { + } + + /** + * Register listener with the Dictionary + *

+ * This method is deprecated, use {@link #registerListener(DictionaryListener dictionaryListener)} instead. + *

+ * @param dictionaryListener + */ + @Override + @Deprecated + public void register(DictionaryListener dictionaryListener) + { + registerListener(dictionaryListener); + } + + /** + * Register with the Dictionary + */ + @Override + public void registerListener(DictionaryListener dictionaryListener) + { + this.dictionaryListenersLock.writeLock().lock(); + try + { + if (!dictionaryListeners.contains(dictionaryListener)) + { + dictionaryListeners.add(dictionaryListener); + } + } + finally + { + this.dictionaryListenersLock.writeLock().unlock(); + } + } + + @Override + public List getDictionaryListeners() + { + // need to hold read lock here + this.dictionaryListenersLock.readLock().lock(); + try + { + return new ArrayList(dictionaryListeners); + } + finally + { + this.dictionaryListenersLock.readLock().unlock(); + } + } + + private Map getThreadLocal() + { + Map map = dictionaryRegistryThreadLocal + .get(); + if (map == null) + { + map = new HashMap(); + dictionaryRegistryThreadLocal.set(map); + } + return map; + } + + private DictionaryRegistry createCoreDictionaryRegistry() + { + DictionaryRegistry dictionaryRegistry = new CoreDictionaryRegistryImpl( + this); + return dictionaryRegistry; + } + + private DictionaryRegistry createTenantDictionaryRegistry( + final String tenant) + { + DictionaryRegistry result = AuthenticationUtil.runAs( + new RunAsWork() + { + public DictionaryRegistry doWork() + { + DictionaryRegistry dictionaryRegistry = new TenantDictionaryRegistryImpl( + DictionaryDAOImpl.this, tenant); + return dictionaryRegistry; + } + }, tenantService.getDomainUser( + AuthenticationUtil.getSystemUserName(), tenant)); + + return result; + } + + @Override + public void init() + { + String tenant = tenantService.getCurrentUserDomain(); + + dictionaryRegistryCache.forceInChangesForThisUncommittedTransaction(tenant); + + if (logger.isDebugEnabled()) + { + logger.debug("Triggered immediate reload of dictionary for tenant " + tenant); + } + } + + @Override + public void destroy() + { + String tenant = tenantService.getCurrentUserDomain(); + + // TODO Should be reworked when ACE-2001 will be implemented + dictionaryRegistryCache.remove(tenant); + + if (logger.isDebugEnabled()) + { + logger.debug("Dictionary destroyed for tenant " + tenant); + } + } + + @Override + public void reset() + { + String tenant = tenantService.getCurrentUserDomain(); + if (logger.isDebugEnabled()) + { + logger.debug("Resetting dictionary for tenant " + tenant); + } + + destroy(); + // Ensure that we have a dictionary available right now + getDictionaryRegistry(tenant); + + if (logger.isDebugEnabled()) + { + logger.debug("Dictionary reset complete for tenant " + tenant); + } + } + + @Override + public QName putModel(M2Model model) + { + // the core registry is not yet initialised so put it in the core registry + QName ret = putModelImpl(model, true); + return ret; + } + + @Override + public QName putModelIgnoringConstraints(M2Model model) + { + return putModelImpl(model, false); + } + + private QName putModelImpl(M2Model model, boolean enableConstraintClassLoading) + { + // Compile model definition + CompiledModel compiledModel = model.compile(this, this, + enableConstraintClassLoading); + QName modelName = compiledModel.getModelDefinition().getName(); + + getTenantDictionaryRegistry().putModel(compiledModel); + + if (logger.isTraceEnabled()) + { + logger.trace("Registered core model: " + + modelName.toPrefixString(this)); + for (M2Namespace namespace : model.getNamespaces()) + { + logger.trace("Registered core namespace: '" + + namespace.getUri() + "' (prefix '" + + namespace.getPrefix() + "')"); + } + } + + return modelName; + } + + /** + * @see org.alfresco.repo.dictionary.DictionaryDAO#removeModel(org.alfresco.service.namespace.QName) + */ + public void removeModel(QName modelName) + { + getTenantDictionaryRegistry().removeModel(modelName); + } + + private DictionaryRegistry getTenantDictionaryRegistry() + { + String tenantDomain = tenantService.getCurrentUserDomain(); + return getDictionaryRegistry(tenantDomain); + } + + /** + * @param modelName + * the model name + * @return the compiled model of the given name + */ + public CompiledModel getCompiledModel(QName modelName) + { + return getTenantDictionaryRegistry().getModel(modelName); + } + + @Override + public DataTypeDefinition getDataType(QName typeName) + { + DataTypeDefinition dataTypeDef = null; + + if (typeName != null) + { + dataTypeDef = getTenantDictionaryRegistry().getDataType(typeName); + } + + return dataTypeDef; + } + + @SuppressWarnings("rawtypes") + @Override + public DataTypeDefinition getDataType(Class javaClass) + { + return getTenantDictionaryRegistry().getDataType(javaClass); + } + + @Override + public Collection getDataTypes(QName modelName) + { + CompiledModel model = getCompiledModel(modelName); + return model.getDataTypes(); + } + + @Override + public TypeDefinition getType(QName typeName) + { + TypeDefinition typeDef = null; + + if (typeName != null) + { + typeDef = getTenantDictionaryRegistry().getType(typeName); + } + + return typeDef; + } + + @Override + public Collection getSubTypes(QName superType, boolean follow) + { + // note: could be optimised further, if compiled into the model + + // Get all types (with parent type) for all models + Map allTypesAndParents = new HashMap(); // name, + // parent + + for (CompiledModel model : getCompiledModels(true).values()) + { + for (TypeDefinition type : model.getTypes()) + { + allTypesAndParents.put(type.getName(), type.getParentName()); + } + } + + // Get sub types + HashSet subTypes = new HashSet(); + for (QName type : allTypesAndParents.keySet()) + { + if (follow) + { + // all sub types + QName current = type; + while ((current != null) && !current.equals(superType)) + { + current = allTypesAndParents.get(current); // get parent + } + if (current != null) + { + subTypes.add(type); + } + } + else + { + // immediate sub types only + QName typesSuperType = allTypesAndParents.get(type); + if (typesSuperType != null && typesSuperType.equals(superType)) + { + subTypes.add(type); + } + } + + } + return subTypes; + } + + @Override + public AspectDefinition getAspect(QName aspectName) + { + AspectDefinition aspectDef = null; + + if (aspectName != null) + { + aspectDef = getTenantDictionaryRegistry().getAspect(aspectName); + } + + return aspectDef; + } + + @Override + public Collection getSubAspects(QName superAspect, boolean follow) + { + // note: could be optimised further, if compiled into the model + + // Get all aspects (with parent aspect) for all models + Map allAspectsAndParents = new HashMap(); // name, + // parent + + for (CompiledModel model : getCompiledModels(true).values()) + { + for (AspectDefinition aspect : model.getAspects()) + { + allAspectsAndParents.put(aspect.getName(), + aspect.getParentName()); + } + } + + // Get sub aspects + HashSet subAspects = new HashSet(); + for (QName aspect : allAspectsAndParents.keySet()) + { + if (follow) + { + // all sub aspects + QName current = aspect; + while ((current != null) && !current.equals(superAspect)) + { + current = allAspectsAndParents.get(current); // get parent + } + if (current != null) + { + subAspects.add(aspect); + } + } + else + { + // immediate sub aspects only + QName typesSuperAspect = allAspectsAndParents.get(aspect); + if (typesSuperAspect != null + && typesSuperAspect.equals(superAspect)) + { + subAspects.add(aspect); + } + } + } + return subAspects; + } + + @Override + public ClassDefinition getClass(QName className) + { + ClassDefinition classDef = null; + + if (className != null) + { + classDef = getTenantDictionaryRegistry().getClass(className); + } + + return classDef; + } + + @Override + public PropertyDefinition getProperty(QName propertyName) + { + PropertyDefinition propertyDef = null; + + if (propertyName != null) + { + propertyDef = getTenantDictionaryRegistry().getProperty( + propertyName); + } + + return propertyDef; + } + + @Override + public ConstraintDefinition getConstraint(QName constraintQName) + { + ConstraintDefinition constraintDef = null; + + if (constraintQName != null) + { + constraintDef = getTenantDictionaryRegistry().getConstraint( + constraintQName); + } + + return constraintDef; + } + + @Override + public AssociationDefinition getAssociation(QName assocName) + { + return getTenantDictionaryRegistry().getAssociation(assocName); + } + + public Collection getAssociations(QName modelName) + { + CompiledModel model = getCompiledModel(modelName); + return model.getAssociations(); + } + + public Collection getModels(boolean includeInherited) + { + // get all models - including inherited models, if applicable + return getCompiledModels(includeInherited).keySet(); + } + + @Override + public Collection getModels() + { + // get all models - including inherited models, if applicable + return getModels(true); + } + + public Collection getTypes(boolean includeInherited) + { + return getTenantDictionaryRegistry().getTypes(includeInherited); + } + + public Collection getAssociations(boolean includeInherited) + { + return getTenantDictionaryRegistry().getAssociations(includeInherited); + } + + public Collection getAspects(boolean includeInherited) + { + return getTenantDictionaryRegistry().getAspects(includeInherited); + } + + // MT-specific + public boolean isModelInherited(QName modelName) + { + return getTenantDictionaryRegistry().isModelInherited(modelName); + } + + private Map getCompiledModels(boolean includeInherited) + { + return getTenantDictionaryRegistry().getCompiledModels(includeInherited); + } + + @Override + public ModelDefinition getModel(QName name) + { + CompiledModel model = getCompiledModel(name); + return model.getModelDefinition(); + } + + @Override + public Collection getTypes(QName modelName) + { + CompiledModel model = getCompiledModel(modelName); + return model.getTypes(); + } + + @Override + public Collection getAspects(QName modelName) + { + CompiledModel model = getCompiledModel(modelName); + return model.getAspects(); + } + + @Override + public TypeDefinition getAnonymousType(QName type, Collection aspects) + { + TypeDefinition typeDef = getType(type); + if (typeDef == null) + { + throw new DictionaryException( + "d_dictionary.model.err.type_not_found", type); + } + Collection aspectDefs = new ArrayList(); + if (aspects != null) + { + for (QName aspect : aspects) + { + AspectDefinition aspectDef = getAspect(aspect); + if (aspectDef == null) + { + throw new DictionaryException( + "d_dictionary.model.err.aspect_not_found", aspect); + } + aspectDefs.add(aspectDef); + } + } + return new M2AnonymousTypeDefinition(typeDef, aspectDefs); + } + + @Override + public Collection getProperties(QName modelName) + { + CompiledModel model = getCompiledModel(modelName); + return model.getProperties(); + } + + @Override + public Collection getProperties(QName modelName, + QName dataType) + { + HashSet properties = new HashSet(); + + Collection props = getProperties(modelName); + for (PropertyDefinition prop : props) + { + if ((dataType == null) + || prop.getDataType().getName().equals(dataType)) + { + properties.add(prop); + } + } + return properties; + } + + @Override + public Collection getPropertiesOfDataType(QName dataType) + { + Collection properties = new HashSet(); + + Collection modelNames = getModels(); + for (QName modelName : modelNames) + { + properties.addAll(getProperties(modelName, dataType)); + } + + return properties; + } + + @Override + public Collection getNamespaces(QName modelName) + { + CompiledModel model = getCompiledModel(modelName); + ModelDefinition modelDef = model.getModelDefinition(); + return modelDef.getNamespaces(); + } + + @Override + public Collection getConstraints(QName modelName) + { + return getConstraints(modelName, false); + } + + public Collection getConstraints(QName modelName, + boolean referenceableDefsOnly) + { + CompiledModel model = getCompiledModel(modelName); + if (referenceableDefsOnly) + { + return getReferenceableConstraintDefs(model); + } + else + { + return model.getConstraints(); + } + } + + private Collection getReferenceableConstraintDefs( + CompiledModel model) + { + Collection conDefs = model.getConstraints(); + Collection propDefs = model.getProperties(); + for (PropertyDefinition propDef : propDefs) + { + for (ConstraintDefinition conDef : propDef.getConstraints()) + { + conDefs.remove(conDef); + } + } + + return conDefs; + } + + // re-entrant (eg. via reset) + @Override + public DictionaryRegistry getDictionaryRegistry(String tenantDomain) + { + DictionaryRegistry dictionaryRegistry = null; + + if (tenantDomain == null) + { + throw new AlfrescoRuntimeException("Tenant must be set"); + } + + // check threadlocal first - return if set + dictionaryRegistry = getThreadLocal().get(tenantDomain); + if (dictionaryRegistry == null) + { + dictionaryRegistry = dictionaryRegistryCache.get(tenantDomain); + } + + return dictionaryRegistry; + } + + /** + * For cache use only. + * + * @param tenantDomain String + * @return constructed DictionaryRegistry + */ + public DictionaryRegistry initDictionaryRegistry(final String tenantDomain) + { + return AuthenticationUtil.runAs( + new RunAsWork() + { + public DictionaryRegistry doWork() + { + DictionaryRegistry dictionaryRegistry = null; + if (tenantDomain.equals(TenantService.DEFAULT_DOMAIN)) + { + dictionaryRegistry = createCoreDictionaryRegistry(); + } + else + { + dictionaryRegistry = createTenantDictionaryRegistry(tenantDomain); + } + + getThreadLocal().put(tenantDomain, dictionaryRegistry); + dictionaryRegistry.init(); + getThreadLocal().remove(tenantDomain); + + return dictionaryRegistry; + } + }, + tenantService.getDomainUser( + AuthenticationUtil.getSystemUserName(), tenantDomain)); + } + + /** + * Return diffs between input model and model in the Dictionary. + * + * If the input model does not exist in the Dictionary then no diffs will be + * returned. + * + * @param model M2Model + * @return model diffs (if any) + */ + public List diffModel(M2Model model) + { + return diffModel(model, true); + } + + public List diffModelIgnoringConstraints(M2Model model) + { + return diffModel(model, false); + } + + /** + * Return diffs between input model and model in the Dictionary. + * + * If the input model does not exist in the Dictionary then no diffs will be + * returned. + * + * @param model M2Model + * @param enableConstraintClassLoading boolean + * @return model diffs (if any) + */ + public List diffModel(M2Model model, + boolean enableConstraintClassLoading) + { + // Compile model definition + CompiledModel compiledModel = model.compile(this, this, + enableConstraintClassLoading); + QName modelName = compiledModel.getModelDefinition().getName(); + + CompiledModel previousVersion = null; + try + { + previousVersion = getCompiledModel(modelName); + } + catch (DictionaryException e) + { + // ignore missing model, there's no need to warn about this. + logger.debug(e); + } + + if (previousVersion == null) + { + return new ArrayList(0); + } + else + { + return diffModel(previousVersion, compiledModel); + } + } + + /** + * Return diffs between two compiled models. + * + * note: - checks classes (types & aspects) for incremental updates - checks + * properties for incremental updates, but does not include the diffs - + * checks assocs & child assocs for incremental updates, but does not + * include the diffs - incremental updates include changes in + * title/description, property default value, etc - ignores changes in model + * definition except name (ie. title, description, author, published date, + * version are treated as an incremental update) + * + * TODO - imports - namespace - datatypes - constraints (including property + * constraints - references and inline) + * + * @param previousVersion CompiledModel + * @param model CompiledModel + * @return model diffs (if any) + */ + /* package */List diffModel(CompiledModel previousVersion, + CompiledModel model) + { + List M2ModelDiffs = new ArrayList(); + + if (previousVersion != null) + { + Collection previousTypes = previousVersion + .getTypes(); + Collection previousAspects = previousVersion + .getAspects(); + Collection previousConDefs = getReferenceableConstraintDefs(previousVersion); + Collection previousImportedNamespaces = previousVersion.getModelDefinition().getImportedNamespaces(); + + if (model == null) + { + // delete model + for (TypeDefinition previousType : previousTypes) + { + M2ModelDiffs.add(new M2ModelDiff(previousType.getName(), + M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_DELETED)); + } + for (AspectDefinition previousAspect : previousAspects) + { + M2ModelDiffs.add(new M2ModelDiff(previousAspect.getName(), + M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_DELETED)); + } + for (ConstraintDefinition previousConDef : previousConDefs) + { + M2ModelDiffs.add(new M2ModelDiff(previousConDef.getName(), + M2ModelDiff.TYPE_CONSTRAINT, + M2ModelDiff.DIFF_DELETED)); + } + } + else + { + // update model + Collection types = model.getTypes(); + Collection aspects = model.getAspects(); + Collection conDefs = getReferenceableConstraintDefs(model); + Collection importedNamespaces = model.getModelDefinition().getImportedNamespaces(); + + if (previousTypes.size() != 0) + { + M2ModelDiffs.addAll(M2ClassDefinition.diffClassLists( + new ArrayList(previousTypes), + new ArrayList(types), + M2ModelDiff.TYPE_TYPE)); + } + else + { + for (TypeDefinition type : types) + { + M2ModelDiffs + .add(new M2ModelDiff(type.getName(), + M2ModelDiff.TYPE_TYPE, + M2ModelDiff.DIFF_CREATED)); + } + } + + if (previousAspects.size() != 0) + { + M2ModelDiffs.addAll(M2ClassDefinition.diffClassLists( + new ArrayList(previousAspects), + new ArrayList(aspects), + M2ModelDiff.TYPE_ASPECT)); + } + else + { + for (AspectDefinition aspect : aspects) + { + M2ModelDiffs.add(new M2ModelDiff(aspect.getName(), + M2ModelDiff.TYPE_ASPECT, + M2ModelDiff.DIFF_CREATED)); + } + } + + if (previousConDefs.size() != 0) + { + M2ModelDiffs + .addAll(M2ConstraintDefinition + .diffConstraintLists( + new ArrayList( + previousConDefs), + new ArrayList( + conDefs))); + } + else + { + for (ConstraintDefinition conDef : conDefs) + { + M2ModelDiffs.add(new M2ModelDiff(conDef.getName(), + M2ModelDiff.TYPE_CONSTRAINT, + M2ModelDiff.DIFF_CREATED)); + } + } + + if (previousImportedNamespaces.size() != 0) + { + M2ModelDiffs + .addAll(M2NamespaceDefinition + .diffNamespaceDefinitionLists( + new ArrayList( + previousImportedNamespaces), + new ArrayList( + importedNamespaces))); + } + else + { + for(NamespaceDefinition namespaceDefinition: importedNamespaces) + { + M2ModelDiffs.add(new M2ModelDiff(namespaceDefinition.getModel().getName(), + namespaceDefinition, + M2ModelDiff.TYPE_NAMESPACE, + M2ModelDiff.DIFF_CREATED)); + } + } + } + } + else + { + if (model != null) + { + // new model + Collection types = model.getTypes(); + Collection aspects = model.getAspects(); + + for (TypeDefinition type : types) + { + M2ModelDiffs.add(new M2ModelDiff(type.getName(), + M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_CREATED)); + } + + for (AspectDefinition aspect : aspects) + { + M2ModelDiffs.add(new M2ModelDiff(aspect.getName(), + M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_CREATED)); + } + } + else + { + // nothing to diff + } + } + + return M2ModelDiffs; + } + + @Override + public ClassLoader getResourceClassLoader() + { + return resourceClassLoader; + } + + @Override + public void setResourceClassLoader(ClassLoader resourceClassLoader) + { + this.resourceClassLoader = resourceClassLoader; + } + + @Override + public String getNamespaceURI(String prefix) + { + return getTenantDictionaryRegistry().getNamespaceURI(prefix); + } + + @Override + public Collection getPrefixes(String URI) + { + return getTenantDictionaryRegistry().getPrefixes(URI); + } + + @Override + public void addURI(String uri) + { + getTenantDictionaryRegistry().addURI(uri); + } + + @Override + public Collection getPrefixes() + { + return Collections.unmodifiableCollection(getTenantDictionaryRegistry() + .getPrefixesCache().keySet()); + } + + @Override + public Collection getURIs() + { + return Collections.unmodifiableCollection(getTenantDictionaryRegistry() + .getUrisCache()); + } + + @Override + public void removeURI(String uri) + { + getTenantDictionaryRegistry().removeURI(uri); + } + + @Override + public void addPrefix(String prefix, String uri) + { + getTenantDictionaryRegistry().addPrefix(prefix, uri); + } + + @Override + public void removePrefix(String prefix) + { + getTenantDictionaryRegistry().removePrefix(prefix); + } + + private AtomicBoolean contextRefreshed = new AtomicBoolean(false); + + @Override + public boolean isContextRefreshed() + { + return contextRefreshed.get(); + } + + @Override + public void onApplicationEvent(ApplicationEvent event) + { + if (event instanceof ContextRefreshedEvent) + { + contextRefreshed.set(true); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryListener.java b/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryListener.java new file mode 100644 index 0000000000..5c1708389b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryListener.java @@ -0,0 +1,50 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +/** + * Dictionary Listener interface. + *

+ * This interface allows Dictionary Listeners to register with the DictionaryService. + * + */ +public interface DictionaryListener +{ + /** + * Callback for (re-)initialising the Dictionary caches (executed in the current tenant context) + */ + void onDictionaryInit(); + + /** + * Callback once dictionary destroy is complete (executed in the current tenant context) + */ + void afterDictionaryDestroy(); + + /** + * Callback once dictionary initialisation is complete (executed in the current tenant context) + */ + void afterDictionaryInit(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryNamespaceComponent.java b/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryNamespaceComponent.java new file mode 100644 index 0000000000..3bdb0b9865 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryNamespaceComponent.java @@ -0,0 +1,111 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.Collection; + +import org.alfresco.service.namespace.NamespaceService; + + +/** + * Data Dictionary Namespace Service Implementation + * + * @author David Caruana + */ +public class DictionaryNamespaceComponent implements NamespaceService +{ + /** + * Namespace DAO + */ + private NamespaceDAO namespaceDAO; + + + /** + * Sets the Namespace DAO + * + * @param namespaceDAO namespace DAO + */ + public void setNamespaceDAO(NamespaceDAO namespaceDAO) + { + this.namespaceDAO = namespaceDAO; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.NamespaceService#getURIs() + */ + public Collection getURIs() + { + return namespaceDAO.getURIs(); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.NamespaceService#getPrefixes() + */ + public Collection getPrefixes() + { + return namespaceDAO.getPrefixes(); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.ref.NamespacePrefixResolver#getNamespaceURI(java.lang.String) + */ + public String getNamespaceURI(String prefix) + { + return namespaceDAO.getNamespaceURI(prefix); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.ref.NamespacePrefixResolver#getPrefixes(java.lang.String) + */ + public Collection getPrefixes(String namespaceURI) + { + return namespaceDAO.getPrefixes(namespaceURI); + } + + + /* (non-Javadoc) + * @see org.alfresco.service.namespace.NamespaceService#registerNamespace(java.lang.String, java.lang.String) + */ + public void registerNamespace(String prefix, String uri) + { + // TODO: + throw new UnsupportedOperationException(); + } + + + /* (non-Javadoc) + * @see org.alfresco.service.namespace.NamespaceService#registerNamespace(java.lang.String, java.lang.String) + */ + public void unregisterNamespace(String prefix) + { + // TODO: + throw new UnsupportedOperationException(); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryRegistry.java b/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryRegistry.java new file mode 100644 index 0000000000..b8686dc8c1 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/DictionaryRegistry.java @@ -0,0 +1,82 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.QName; + +/** + * + * @author sglover + * + */ +public interface DictionaryRegistry +{ + void init(); + void remove(); + CompiledModel getModel(QName name); + boolean modelExists(QName name); + Map> getUriToModels(); + Map getCompiledModels(boolean includeInherited); + QName putModel(CompiledModel model); + void removeModel(QName modelName); + String getTenantDomain(); + void clear(); + List getModelsForUri(String uri); + AspectDefinition getAspect(QName aspectName); + AssociationDefinition getAssociation(QName assocName); + ClassDefinition getClass(QName className); + PropertyDefinition getProperty(QName propertyName); + TypeDefinition getType(QName typeName); + ConstraintDefinition getConstraint(QName constraintQName); + DataTypeDefinition getDataType(QName typeName); + @SuppressWarnings("rawtypes") + DataTypeDefinition getDataType(Class javaClass); + boolean isModelInherited(QName modelName); + Map getPrefixesCache(); + List getUrisCache(); + Collection getPrefixes(String URI); + void addURI(String uri); + boolean hasURI(String uri); + void addPrefix(String prefix, String uri); + boolean hasPrefix(String prefix); + void removeURI(String uri); + void removePrefix(String prefix); + Collection getTypes(boolean includeInherited); + Collection getAssociations(boolean includeInherited); + Collection getAspects(boolean includeInherited); + String getNamespaceURI(String prefix); +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/ExtendedDictionaryListener.java b/data-model/src/main/java/org/alfresco/repo/dictionary/ExtendedDictionaryListener.java new file mode 100644 index 0000000000..a7752ef788 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/ExtendedDictionaryListener.java @@ -0,0 +1,39 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +/** + * A dictionary listener that allows listeners to listen for models being added to + * the dictionary. Used by the OpenCMIS dictionary to refresh its registry when new models + * are added to the core dictionary. + * + * @author sglover + * + */ +public interface ExtendedDictionaryListener extends DictionaryListener +{ + void modelAdded(CompiledModel model, String tenant); +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/Facetable.java b/data-model/src/main/java/org/alfresco/repo/dictionary/Facetable.java new file mode 100644 index 0000000000..98fe2383ab --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/Facetable.java @@ -0,0 +1,67 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +/** + * How faceting is to be supported + * + * @author Andy + * + */ +public enum Facetable +{ + /** + * TRUE - faceting is required and enhanced support for this is provided if possible + */ + TRUE, + /** + * UNSET - facet support is unset, standard support is assumed + */ + UNSET, + /** + * FALSE - feceting is not required and will not be supported + */ + FALSE; + + public static String serializer(Facetable facetable) { + return facetable.toString(); + } + + public static Facetable deserializer(String value) { + if (value == null) { + return null; + } else if (value.equalsIgnoreCase(TRUE.toString())) { + return TRUE; + } else if (value.equalsIgnoreCase(FALSE.toString())) { + return FALSE; + } else if (value.equalsIgnoreCase(UNSET.toString())) { + return UNSET; + } else { + throw new IllegalArgumentException( + "Invalid facetable enum value: " + value); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/IndexTokenisationMode.java b/data-model/src/main/java/org/alfresco/repo/dictionary/IndexTokenisationMode.java new file mode 100644 index 0000000000..1b53a5374f --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/IndexTokenisationMode.java @@ -0,0 +1,70 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +/** + * How tokenisation is supported in the index. + * + * + * @author andyh + * + */ +public enum IndexTokenisationMode { + /** + * Tokenise the property. If the analyser supported ordering then the field + * supports ordering FTS is supported via analysis. + */ + TRUE, + /** + * Do not tokenise the property. The field supports ordering and pattern + * matching. + */ + FALSE, + /** + * There may be two indexes - one to support ordering and one to support + * search. + */ + BOTH; + + public static String serializer(IndexTokenisationMode indexTokenisationMode) { + return indexTokenisationMode.toString(); + } + + public static IndexTokenisationMode deserializer(String value) { + if (value == null) { + return null; + } else if (value.equalsIgnoreCase(TRUE.toString())) { + return TRUE; + } else if (value.equalsIgnoreCase(FALSE.toString())) { + return FALSE; + } else if (value.equalsIgnoreCase(BOTH.toString())) { + return BOTH; + } else { + throw new IllegalArgumentException( + "Invalid IndexTokenisationMode: " + value); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2AnonymousTypeDefinition.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2AnonymousTypeDefinition.java new file mode 100644 index 0000000000..3a315ea2f5 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2AnonymousTypeDefinition.java @@ -0,0 +1,255 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.i18n.StaticMessageLookup; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + + +/** + * Compiled anonymous type definition. + * + * @author David Caruana + * + */ +/*package*/ class M2AnonymousTypeDefinition implements TypeDefinition +{ + private TypeDefinition type; + private Map properties = new HashMap(); + private Map associations = new HashMap(); + private Map childassociations = new HashMap(); + private transient MessageLookup staticMessageLookup = new StaticMessageLookup(); + + /** + * Construct + * + * @param type the primary type + * @param aspects the aspects to combine with the type + */ + /*package*/ M2AnonymousTypeDefinition(TypeDefinition type, Collection aspects) + { + this.type = type; + + // Combine features of type and aspects + properties.putAll(type.getProperties()); + associations.putAll(type.getAssociations()); + childassociations.putAll(type.getChildAssociations()); + for (AspectDefinition aspect : aspects) + { + properties.putAll(aspect.getProperties()); + associations.putAll(aspect.getAssociations()); + childassociations.putAll(aspect.getChildAssociations()); + } + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getModel() + */ + public ModelDefinition getModel() + { + return type.getModel(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.TypeDefinition#getDefaultAspects() + */ + public List getDefaultAspects() + { + return type.getDefaultAspects(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getDefaultAspects(boolean) + */ + public List getDefaultAspects(boolean inherited) + { + return type.getDefaultAspects(inherited); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getDefaultAspectNames() + */ + public Set getDefaultAspectNames() + { + return type.getDefaultAspectNames(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#getName() + */ + public QName getName() + { + return QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "anonymous#" + type.getName().getLocalName()); + } + + @Override + public String getDescription() + { + return getDescription(staticMessageLookup); + } + + @Override + public String getTitle() + { + return getTitle(staticMessageLookup); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#getTitle() + */ + public String getTitle(MessageLookup messageLookup) + { + return type.getTitle(messageLookup); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#getDescription() + */ + public String getDescription(MessageLookup messageLookup) + { + return type.getDescription(messageLookup); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#getParentName() + */ + public QName getParentName() + { + return type.getParentName(); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#isAspect() + */ + public boolean isAspect() + { + return type.isAspect(); + } + + public Boolean getArchive() + { + return type.getArchive(); + } + + public Boolean getIncludedInSuperTypeQuery() + { + return type.getIncludedInSuperTypeQuery(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#getProperties() + */ + public Map getProperties() + { + return Collections.unmodifiableMap(properties); + } + + /** + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getDefaultValues() + */ + public Map getDefaultValues() + { + Map result = new HashMap(5); + + for(Map.Entry entry : properties.entrySet()) + { + PropertyDefinition propertyDefinition = entry.getValue(); + String defaultValue = propertyDefinition.getDefaultValue(); + if (defaultValue != null) + { + result.put(entry.getKey(), defaultValue); + } + } + + return Collections.unmodifiableMap(result); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#getAssociations() + */ + public Map getAssociations() + { + return Collections.unmodifiableMap(associations); + } + + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#isContainer() + */ + public boolean isContainer() + { + return !childassociations.isEmpty(); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#getChildAssociations() + */ + public Map getChildAssociations() + { + return Collections.unmodifiableMap(childassociations); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getAnalyserResourceBundleName() + */ + @Override + public String getAnalyserResourceBundleName() + { + return type.getAnalyserResourceBundleName(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getParentClassDefinition() + */ + @Override + public ClassDefinition getParentClassDefinition() + { + return type.getParentClassDefinition(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2Aspect.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Aspect.java new file mode 100644 index 0000000000..9442dea03a --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Aspect.java @@ -0,0 +1,41 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +/** + * Aspect definition. + * + * @author David Caruana + */ +public class M2Aspect extends M2Class +{ + + /*package*/ M2Aspect() + { + super(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2AspectDefinition.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2AspectDefinition.java new file mode 100644 index 0000000000..834f92bc95 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2AspectDefinition.java @@ -0,0 +1,80 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.Map; + +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; + + +/** + * Compiled Aspect Definition. + * + * @author David Caruana + */ +/*package*/ class M2AspectDefinition extends M2ClassDefinition + implements AspectDefinition +{ + + /*package*/ M2AspectDefinition(ModelDefinition model, M2Aspect m2Aspect, NamespacePrefixResolver resolver, Map modelProperties, Map modelAssociations) + { + super(model, m2Aspect, resolver, modelProperties, modelAssociations); + } + + @Override + public String getDescription(MessageLookup messageLookup) + { + String value = M2Label.getLabel(model, messageLookup, "aspect", name, "description"); + + // if we don't have a description call the super class + if (value == null) + { + value = super.getDescription(messageLookup); + } + + return value; + } + + @Override + public String getTitle(MessageLookup messageLookup) + { + String value = M2Label.getLabel(model, messageLookup, "aspect", name, "title"); + + // if we don't have a title call the super class + if (value == null) + { + value = super.getTitle(messageLookup); + } + + return value; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2Association.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Association.java new file mode 100644 index 0000000000..ce70e64177 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Association.java @@ -0,0 +1,46 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + + +/** + * Association definition. + * + * @author David Caruana + */ +public class M2Association extends M2ClassAssociation +{ + + /*package*/ M2Association() + { + } + + /*package*/ M2Association(String name) + { + super(name); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2AssociationDefinition.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2AssociationDefinition.java new file mode 100644 index 0000000000..167791a1a2 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2AssociationDefinition.java @@ -0,0 +1,356 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.alfresco.repo.i18n.StaticMessageLookup; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.EqualsHelper; + + +/** + * Compiled Association Definition. + * + * @author David Caruana + */ +/*package*/ class M2AssociationDefinition implements AssociationDefinition +{ + + private ClassDefinition classDef; + private M2ClassAssociation assoc; + private QName name; + private QName targetClassName; + private ClassDefinition targetClass; + private QName sourceRoleName; + private QName targetRoleName; + private transient MessageLookup staticMessageLookup = new StaticMessageLookup(); + + + /** + * Construct + * + * @param classDef ClassDefinition + * @param assoc M2ClassAssociation + * @param resolver NamespacePrefixResolver + */ + /*package*/ M2AssociationDefinition(ClassDefinition classDef, M2ClassAssociation assoc, NamespacePrefixResolver resolver) + { + this.classDef = classDef; + this.assoc = assoc; + + // Resolve names + this.name = QName.createQName(assoc.getName(), resolver); + this.targetClassName = QName.createQName(assoc.getTargetClassName(), resolver); + this.sourceRoleName = QName.createQName(assoc.getSourceRoleName(), resolver); + this.targetRoleName = QName.createQName(assoc.getTargetRoleName(), resolver); + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(56); + sb.append("Association") + .append("[ class=").append(classDef) + .append(", name=").append(name) + .append(", target class=").append(targetClassName) + .append(", source role=").append(sourceRoleName) + .append(", target role=").append(targetRoleName) + .append("]"); + return sb.toString(); + } + + + /*package*/ M2ClassAssociation getM2Association() + { + return assoc; + } + + + /*package*/ void resolveDependencies(ModelQuery query) + { + if (targetClassName == null) + { + throw new DictionaryException("d_dictionary.association.target_class_not_specified", name.toPrefixString()); + } + targetClass = query.getClass(targetClassName); + if (targetClass == null) + { + throw new DictionaryException("d_dictionary.association.target_class_not_found", targetClassName.toPrefixString(), name.toPrefixString()); + } + } + + + @Override + public ModelDefinition getModel() + { + return classDef.getModel(); + } + + + @Override + public QName getName() + { + return name; + } + + + @Override + public boolean isChild() + { + return (assoc instanceof M2ChildAssociation); + } + + @Override + public String getTitle() + { + return getTitle(staticMessageLookup); + } + + @Override + public String getDescription() + { + return getDescription(staticMessageLookup); + } + + @Override + public String getTitle(MessageLookup messageLookup) + { + String value = M2Label.getLabel(classDef.getModel(), messageLookup, "association", name, "title"); + if (value == null) + { + value = assoc.getTitle(); + } + return value; + } + + + @Override + public String getDescription(MessageLookup messageLookup) + { + String value = M2Label.getLabel(classDef.getModel(), messageLookup, "association", name, "description"); + if (value == null) + { + value = assoc.getDescription(); + } + return value; + } + + + @Override + public boolean isProtected() + { + return assoc.isProtected(); + } + + + @Override + public ClassDefinition getSourceClass() + { + return classDef; + } + + + @Override + public QName getSourceRoleName() + { + return sourceRoleName; + } + + + @Override + public boolean isSourceMandatory() + { + return assoc.isSourceMandatory(); + } + + + @Override + public boolean isSourceMany() + { + return assoc.isSourceMany(); + } + + + @Override + public ClassDefinition getTargetClass() + { + return targetClass; + } + + + @Override + public QName getTargetRoleName() + { + return targetRoleName; + } + + + @Override + public boolean isTargetMandatory() + { + return assoc.isTargetMandatory(); + } + + + @Override + public boolean isTargetMandatoryEnforced() + { + return assoc.isTargetMandatoryEnforced(); + } + + + @Override + public boolean isTargetMany() + { + return assoc.isTargetMany(); + } + + /* package */ M2ModelDiff diffAssoc(AssociationDefinition assocDef) + { + M2ModelDiff modelDiff = null; + boolean isUpdated = false; + boolean isUpdatedIncrementally = false; + + if (this == assocDef) + { + modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_UNCHANGED); + return modelDiff; + } + + // check name - cannot be null + if (! name.equals(assocDef.getName())) + { + isUpdated = true; + } + + // check title + if (! EqualsHelper.nullSafeEquals(getTitle(null), assocDef.getTitle(null), false)) + { + isUpdatedIncrementally = true; + } + + // check description + if (! EqualsHelper.nullSafeEquals(getDescription(null), assocDef.getDescription(null), false)) + { + isUpdatedIncrementally = true; + } + + // check source class qname + if (! EqualsHelper.nullSafeEquals(getSourceClass().getName(), assocDef.getSourceClass().getName())) + { + isUpdated = true; + } + + // check source role qname + if (! EqualsHelper.nullSafeEquals(getSourceRoleName(), assocDef.getSourceRoleName())) + { + isUpdated = true; + } + + // check target class qname + if (! EqualsHelper.nullSafeEquals(getTargetClass().getName(), assocDef.getTargetClass().getName())) + { + isUpdated = true; + } + + // check target role qname + if (! EqualsHelper.nullSafeEquals(getTargetRoleName(), assocDef.getTargetRoleName())) + { + isUpdated = true; + } + + // TODO - additional checks - is... (x7) + + if (isUpdated) + { + modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_UPDATED); + } + else if (isUpdatedIncrementally) + { + modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_UPDATED_INC); + } + else + { + modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_UNCHANGED); + } + + return modelDiff; + } + + /*package*/ static Collection diffAssocLists(Collection previousAssocs, Collection newAssocs) + { + List modelDiffs = new ArrayList(); + + for (AssociationDefinition previousAssoc : previousAssocs) + { + boolean found = false; + for (AssociationDefinition newAssoc : newAssocs) + { + if (newAssoc.getName().equals(previousAssoc.getName())) + { + modelDiffs.add(((M2AssociationDefinition)previousAssoc).diffAssoc(newAssoc)); + found = true; + break; + } + } + + if (! found) + { + modelDiffs.add(new M2ModelDiff(previousAssoc.getName(), M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_DELETED)); + } + } + + for (AssociationDefinition newAssoc : newAssocs) + { + boolean found = false; + for (AssociationDefinition previousAssoc : previousAssocs) + { + if (newAssoc.getName().equals(previousAssoc.getName())) + { + found = true; + break; + } + } + + if (! found) + { + modelDiffs.add(new M2ModelDiff(newAssoc.getName(), M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_CREATED)); + } + } + + return modelDiffs; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2ChildAssociation.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2ChildAssociation.java new file mode 100644 index 0000000000..fce0f423f2 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2ChildAssociation.java @@ -0,0 +1,85 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + + +/** + * Child Association definition. + * + * @author David Caruana + * + */ +public class M2ChildAssociation extends M2ClassAssociation +{ + private String requiredChildName = null; + private Boolean allowDuplicateChildName = null; + private Boolean propagateTimestamps = null; + + + /*package*/ M2ChildAssociation() + { + } + + + /*package*/ M2ChildAssociation(String name) + { + super(name); + } + + + public String getRequiredChildName() + { + return requiredChildName; + } + + + public void setRequiredChildName(String requiredChildName) + { + this.requiredChildName = requiredChildName; + } + + + public boolean allowDuplicateChildName() + { + return allowDuplicateChildName == null ? true : allowDuplicateChildName; + } + + + public void setAllowDuplicateChildName(boolean allowDuplicateChildName) + { + this.allowDuplicateChildName = allowDuplicateChildName; + } + + public boolean isPropagateTimestamps() + { + return propagateTimestamps == null ? false : propagateTimestamps; + } + + public void setPropagateTimestamps(boolean propagateTimestamps) + { + this.propagateTimestamps = propagateTimestamps; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2ChildAssociationDefinition.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2ChildAssociationDefinition.java new file mode 100644 index 0000000000..d8c2fcd320 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2ChildAssociationDefinition.java @@ -0,0 +1,70 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.namespace.NamespacePrefixResolver; + + +/** + * Compiled Association Definition. + * + * @author David Caruana + */ +/*package*/ class M2ChildAssociationDefinition extends M2AssociationDefinition + implements ChildAssociationDefinition +{ + + /** + * Construct + * @param classDef class definition + * @param assoc child assocation + * @param resolver namespace resolver + */ + /*package*/ M2ChildAssociationDefinition(ClassDefinition classDef, M2ChildAssociation assoc, NamespacePrefixResolver resolver) + { + super(classDef, assoc, resolver); + } + + + public String getRequiredChildName() + { + return ((M2ChildAssociation)getM2Association()).getRequiredChildName(); + } + + + public boolean getDuplicateChildNamesAllowed() + { + return ((M2ChildAssociation)getM2Association()).allowDuplicateChildName(); + } + + + public boolean getPropagateTimestamps() + { + return ((M2ChildAssociation)getM2Association()).isPropagateTimestamps(); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2Class.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Class.java new file mode 100644 index 0000000000..8bf8738c4f --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Class.java @@ -0,0 +1,304 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Properties; +import java.util.regex.Pattern; + +/** + * Abstract Class Definition. + * + * @author David Caruana + * + */ +public abstract class M2Class +{ + public static final Pattern PROPERTY_PLACEHOLDER = Pattern.compile("\\$\\{.*\\}\\|.*"); + + private String name = null; + private String title = null; + private String description = null; + private String parentName = null; + private Boolean archive = null; + private Boolean includedInSuperTypeQuery = null; + private String analyserResourceBundleName = null; + + private List properties = new ArrayList(); + private List propertyOverrides = new ArrayList(); + private List associations = new ArrayList(); + private List mandatoryAspects = new ArrayList(); + + /*package*/ M2Class() + { + } + + public boolean isAspect() + { + return this instanceof M2Aspect; + } + + + public String getName() + { + return name; + } + + + public void setName(String name) + { + this.name = name; + } + + + public String getTitle() + { + return title; + } + + + public void setTitle(String title) + { + this.title = title; + } + + + public String getDescription() + { + return description; + } + + + public void setDescription(String description) + { + this.description = description; + } + + + public String getParentName() + { + return parentName; + } + + + public void setParentName(String parentName) + { + this.parentName = parentName; + } + + + public Boolean getArchive() + { + return archive; + } + + public void setArchive(boolean archive) + { + this.archive = Boolean.valueOf(archive); + } + + public Boolean getIncludedInSuperTypeQuery() + { + return includedInSuperTypeQuery; + } + + public void setIncludedInSuperTypeQuery(boolean includedInSuperTypeQuery) + { + this.includedInSuperTypeQuery = Boolean.valueOf(includedInSuperTypeQuery); + } + + public M2Property createProperty(String name) + { + M2Property property = new M2Property(); + property.setName(name); + properties.add(property); + return property; + } + + + public void removeProperty(String name) + { + M2Property property = getProperty(name); + if (property != null) + { + properties.remove(property); + } + } + + + public List getProperties() + { + return Collections.unmodifiableList(properties); + } + + + public M2Property getProperty(String name) + { + for (M2Property candidate : properties) + { + if (candidate.getName().equals(name)) + { + return candidate; + } + } + return null; + } + + + public M2Association createAssociation(String name) + { + M2Association association = new M2Association(); + association.setName(name); + associations.add(association); + return association; + } + + + public M2ChildAssociation createChildAssociation(String name) + { + M2ChildAssociation association = new M2ChildAssociation(); + association.setName(name); + associations.add(association); + return association; + } + + + public void removeAssociation(String name) + { + M2ClassAssociation association = getAssociation(name); + if (association != null) + { + associations.remove(association); + } + } + + + public List getAssociations() + { + return Collections.unmodifiableList(associations); + } + + + public M2ClassAssociation getAssociation(String name) + { + for (M2ClassAssociation candidate : associations) + { + if (candidate.getName().equals(name)) + { + return candidate; + } + } + return null; + } + + + public M2PropertyOverride createPropertyOverride(String name) + { + M2PropertyOverride property = new M2PropertyOverride(); + property.setName(name); + propertyOverrides.add(property); + return property; + } + + + public void removePropertyOverride(String name) + { + M2PropertyOverride property = getPropertyOverride(name); + if (property != null) + { + propertyOverrides.remove(property); + } + } + + + public List getPropertyOverrides() + { + return Collections.unmodifiableList(propertyOverrides); + } + + + public M2PropertyOverride getPropertyOverride(String name) + { + for (M2PropertyOverride candidate : propertyOverrides) + { + if (candidate.getName().equals(name)) + { + return candidate; + } + } + return null; + } + + public void addMandatoryAspect(String name) + { + mandatoryAspects.add(name); + } + + + public void removeMandatoryAspect(String name) + { + mandatoryAspects.remove(name); + } + + + public List getMandatoryAspects() + { + return Collections.unmodifiableList(mandatoryAspects); + } + + /** + * @return String + */ + public String getAnalyserResourceBundleName() + { + return analyserResourceBundleName; + } + + public void setAnalyserResourceBundleName(String analyserResourceBundleName) + { + this.analyserResourceBundleName = analyserResourceBundleName; + } + + public void setConfigProperties(Properties configProperties) + { + if (properties != null) + { + for (M2Property property : properties) + { + property.setConfigProperties(configProperties); + } + } + if (propertyOverrides != null) + { + for (M2PropertyOverride propertyOverride : propertyOverrides) + { + propertyOverride.setConfigProperties(configProperties); + } + } + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2ClassAssociation.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2ClassAssociation.java new file mode 100644 index 0000000000..a2c469f1af --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2ClassAssociation.java @@ -0,0 +1,219 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + + +/** + * Abstract Association Definition. + * + * @author David Caruana + * + */ +public abstract class M2ClassAssociation +{ + private String name = null; + private Boolean isProtected = null; + private String title = null; + private String description = null; + private String sourceRoleName = null; + private Boolean isSourceMandatory = null; + private Boolean isSourceMany = null; + private String targetClassName = null; + private String targetRoleName = null; + private Boolean isTargetMandatory = null; + private Boolean isTargetMandatoryEnforced = null; + private Boolean isTargetMany = null; + + + /*package*/ M2ClassAssociation() + { + } + + + /*package*/ M2ClassAssociation(String name) + { + this.name = name; + } + + + public boolean isChild() + { + return this instanceof M2ChildAssociation; + } + + + public String getName() + { + return name; + } + + + public void setName(String name) + { + this.name = name; + } + + + public boolean isProtected() + { + return isProtected == null ? false : isProtected; + } + + + public void setProtected(boolean isProtected) + { + this.isProtected = isProtected; + } + + + public String getTitle() + { + return title; + } + + + public void setTitle(String title) + { + this.title = title; + } + + + public String getDescription() + { + return description; + } + + + public void setDescription(String description) + { + this.description = description; + } + + + public String getSourceRoleName() + { + return sourceRoleName; + } + + + public void setSourceRoleName(String name) + { + this.sourceRoleName = name; + } + + + public boolean isSourceMandatory() + { + return isSourceMandatory == null ? true : isSourceMandatory; + } + + + public void setSourceMandatory(boolean isSourceMandatory) + { + this.isSourceMandatory = isSourceMandatory; + } + + + public boolean isSourceMany() + { + return isSourceMany == null ? false : isSourceMany; + } + + + public void setSourceMany(boolean isSourceMany) + { + this.isSourceMany = isSourceMany; + } + + + public String getTargetClassName() + { + return targetClassName; + } + + + public void setTargetClassName(String targetClassName) + { + this.targetClassName = targetClassName; + } + + + public String getTargetRoleName() + { + return targetRoleName; + } + + + public void setTargetRoleName(String name) + { + this.targetRoleName = name; + } + + public Boolean getTargetMandatory() + { + return isTargetMandatory(); + } + + public boolean isTargetMandatory() + { + return isTargetMandatory == null ? false : isTargetMandatory; + } + + + public void setTargetMandatory(boolean isTargetMandatory) + { + this.isTargetMandatory = isTargetMandatory; + } + + public Boolean getTargetMandatoryEnforced() + { + return isTargetMandatoryEnforced(); + } + + public boolean isTargetMandatoryEnforced() + { + return isTargetMandatoryEnforced == null ? isTargetMandatory() : isTargetMandatoryEnforced; + } + + + public void setTargetMandatoryEnforced(boolean isTargetMandatoryEnforced) + { + this.isTargetMandatoryEnforced = isTargetMandatoryEnforced; + } + + + public boolean isTargetMany() + { + return isTargetMany == null ? true : isTargetMany; + } + + + public void setTargetMany(boolean isTargetMany) + { + this.isTargetMany = isTargetMany; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2ClassDefinition.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2ClassDefinition.java new file mode 100644 index 0000000000..afca702a0f --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2ClassDefinition.java @@ -0,0 +1,781 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import static org.alfresco.service.cmr.dictionary.DictionaryException.DuplicateDefinitionException; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.i18n.StaticMessageLookup; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.EqualsHelper; + + +/** + * Compiled Class Definition + * + * @author David Caruana + */ +/*package*/ class M2ClassDefinition implements ClassDefinition +{ + private static final String ERR_CLASS_NOT_DEFINED_NAMESPACE = "d_dictionary.class_definition.class.namespace_not_defined"; + private static final String ERR_PROPERTY_NOT_DEFINED_NAMESPACE = "d_dictionary.class_definition.property.namespace_not_defined"; + private static final String ERR_DUPLICATE_PROPERTY_DEFINITION = "d_dictionary.class_definition.duplicate.property_definition"; + private static final String ERR_DUPLICATE_PROPERTY_EXISTING_DEF = "d_dictionary.class_definition.duplicate.property_existing_def"; + private static final String ERR_ASSOCIATION_NOT_DEFINED_NAMESPACE = "d_dictionary.class_definition.association.namespace_not_defined"; + private static final String ERR_DUPLICATE_ASSOCIATION_DEFINITION = "d_dictionary.class_definition.duplicate.association_definition"; + private static final String ERR_DUPLICATE_ASSOCIATION_EXISTING_DEF = "d_dictionary.class_definition.duplicate.association_existing_def"; + private static final String ERR_DUPLICATE_PROPERTY_AND_PROPERTY_OVERRIDE = "d_dictionary.class_definition.duplicate.property_and_property_override"; + private static final String ERR_DUPLICATE_PROPERTY_OVERRIDE = "d_dictionary.class_definition.duplicate.property_override_definition"; + private static final String ERR_PARENT_NOT_FOUND = "d_dictionary.class_definition.class.parent_not_found"; + private static final String ERR_PROPERTY_NOT_EXIST = "d_dictionary.class_definition.property_not_exist"; + private static final String ERR_MANDATORY_ASPECT_NOT_FOUND = "d_dictionary.class_definition.mandatory_aspect_not_found"; + private static final String ERR_DUPLICATE_PROPERTY_IN_CLASS_HIERARCHY = "d_dictionary.class_definition.duplicate.property_in_class_hierarchy"; + private static final String ERR_DUPLICATE_ASSOCIATION_IN_CLASS_HIERARCHY = "d_dictionary.class_definition.duplicate.association_in_class_hierarchy"; + + protected ModelDefinition model; + protected M2Class m2Class; + protected QName name; + protected QName parentName = null; + protected ClassDefinition parentClassDefinition; + + private Map propertyOverrides = new HashMap(); + private Map properties = new HashMap(); + private Map inheritedProperties = new HashMap(); + private Map associations = new HashMap(); + private Map inheritedAssociations = new HashMap(); + private Map inheritedChildAssociations = new HashMap(); + private List defaultAspects = new ArrayList(); + private List defaultAspectNames = new ArrayList(); + private List inheritedDefaultAspects = new ArrayList(); + private Set inheritedDefaultAspectNames = new HashSet(); + private Boolean archive = null; + private Boolean inheritedArchive = null; + private Boolean includedInSuperTypeQuery = null; + private Boolean inheritedIncludedInSuperTypeQuery = null; + private String analyserResourceBundleName; + private transient MessageLookup staticMessageLookup = new StaticMessageLookup(); + + /** + * Construct + * + * @param m2Class class definition + * @param resolver namepsace resolver + * @param modelProperties global list of model properties + * @param modelAssociations global list of model associations + */ + /*package*/ M2ClassDefinition(ModelDefinition model, M2Class m2Class, NamespacePrefixResolver resolver, Map modelProperties, Map modelAssociations) + { + this.model = model; + this.m2Class = m2Class; + + // Resolve Names + this.name = QName.createQName(m2Class.getName(), resolver); + if (!model.isNamespaceDefined(name.getNamespaceURI())) + { + throw new DictionaryException(ERR_CLASS_NOT_DEFINED_NAMESPACE, name.toPrefixString(), name.getNamespaceURI(), model.getName().toPrefixString()); + } + this.archive = m2Class.getArchive(); + this.includedInSuperTypeQuery = m2Class.getIncludedInSuperTypeQuery(); + if (m2Class.getParentName() != null && m2Class.getParentName().length() > 0) + { + this.parentName = QName.createQName(m2Class.getParentName(), resolver); + } + + // Construct Properties + for (M2Property property : m2Class.getProperties()) + { + PropertyDefinition def = new M2PropertyDefinition(this, property, resolver); + if (!model.isNamespaceDefined(def.getName().getNamespaceURI()) && + !model.isNamespaceImported(def.getName().getNamespaceURI())) + { + throw new DictionaryException(ERR_PROPERTY_NOT_DEFINED_NAMESPACE, def.getName().toPrefixString(), def.getName().getNamespaceURI(), model.getName().toPrefixString()); + } + if (properties.containsKey(def.getName())) + { + throw new DuplicateDefinitionException(ERR_DUPLICATE_PROPERTY_DEFINITION, def.getName().toPrefixString(), name.toPrefixString()); + } + + // Check for existence of property elsewhere within the model + PropertyDefinition existingDef = modelProperties.get(def.getName()); + if (existingDef != null) + { + // TODO: Consider sharing property, if property definitions are equal + throw new DuplicateDefinitionException(ERR_DUPLICATE_PROPERTY_EXISTING_DEF, def.getName().toPrefixString(), name.toPrefixString(), existingDef.getContainerClass().getName().toPrefixString()); + } + + properties.put(def.getName(), def); + modelProperties.put(def.getName(), def); + } + + // Construct Associations + for (M2ClassAssociation assoc : m2Class.getAssociations()) + { + AssociationDefinition def; + if (assoc instanceof M2ChildAssociation) + { + def = new M2ChildAssociationDefinition(this, (M2ChildAssociation)assoc, resolver); + } + else + { + def = new M2AssociationDefinition(this, assoc, resolver); + } + if (!model.isNamespaceDefined(def.getName().getNamespaceURI())) + { + throw new DictionaryException(ERR_ASSOCIATION_NOT_DEFINED_NAMESPACE, def.getName().toPrefixString(), def.getName().getNamespaceURI(), model.getName().toPrefixString()); + } + if (associations.containsKey(def.getName())) + { + throw new DuplicateDefinitionException(ERR_DUPLICATE_ASSOCIATION_DEFINITION, def.getName().toPrefixString(), name.toPrefixString()); + } + + // Check for existence of association elsewhere within the model + AssociationDefinition existingDef = modelAssociations.get(def.getName()); + if (existingDef != null) + { + // TODO: Consider sharing association, if association definitions are equal + throw new DuplicateDefinitionException(ERR_DUPLICATE_ASSOCIATION_EXISTING_DEF, def.getName().toPrefixString(), name.toPrefixString(), existingDef.getSourceClass().getName().toPrefixString()); + } + + associations.put(def.getName(), def); + modelAssociations.put(def.getName(), def); + } + + // Construct Property overrides + for (M2PropertyOverride override : m2Class.getPropertyOverrides()) + { + QName overrideName = QName.createQName(override.getName(), resolver); + if (properties.containsKey(overrideName)) + { + throw new DuplicateDefinitionException(ERR_DUPLICATE_PROPERTY_AND_PROPERTY_OVERRIDE, overrideName.toPrefixString(), name.toPrefixString()); + } + if (propertyOverrides.containsKey(overrideName)) + { + throw new DuplicateDefinitionException(ERR_DUPLICATE_PROPERTY_OVERRIDE, overrideName.toPrefixString(), name.toPrefixString()); + } + propertyOverrides.put(overrideName, override); + } + + // Resolve qualified names + for (String aspectName : m2Class.getMandatoryAspects()) + { + QName name = QName.createQName(aspectName, resolver); + if (!defaultAspectNames.contains(name)) + { + defaultAspectNames.add(name); + } + } + + this.analyserResourceBundleName = m2Class.getAnalyserResourceBundleName(); + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(120); + sb.append("ClassDef") + .append("[name=").append(name) + .append("]"); + return sb.toString(); + } + + + /*package*/ void resolveDependencies( + ModelQuery query, + NamespacePrefixResolver prefixResolver, + Map modelConstraints) + { + if (parentName != null) + { + ClassDefinition parent = query.getClass(parentName); + if (parent == null) + { + throw new DictionaryException(ERR_PARENT_NOT_FOUND, parentName.toPrefixString(), name.toPrefixString()); + } + parentClassDefinition = parent; + } + + for (PropertyDefinition def : properties.values()) + { + ((M2PropertyDefinition)def).resolveDependencies(query, prefixResolver, modelConstraints); + } + for (AssociationDefinition def : associations.values()) + { + ((M2AssociationDefinition)def).resolveDependencies(query); + } + + for (Map.Entry override : propertyOverrides.entrySet()) + { + PropertyDefinition propDef = query.getProperty(override.getKey()); + if (propDef == null) + { + throw new DictionaryException(ERR_PROPERTY_NOT_EXIST, name.toPrefixString(), override.getKey().toPrefixString()); + } + } + + for (QName aspectName : defaultAspectNames) + { + AspectDefinition aspect = query.getAspect(aspectName); + if (aspect == null) + { + throw new DictionaryException(ERR_MANDATORY_ASPECT_NOT_FOUND, aspectName.toPrefixString(), name.toPrefixString()); + } + defaultAspects.add(aspect); + } + } + + + /*package*/ void resolveInheritance( + ModelQuery query, + NamespacePrefixResolver prefixResolver, + Map modelConstraints) + { + // Retrieve parent class + ClassDefinition parentClass = (parentName == null) ? null : query.getClass(parentName); + + // Build list of inherited properties (and process overridden values) + if (parentClass != null) + { + for (PropertyDefinition def : parentClass.getProperties().values()) + { + M2PropertyOverride override = propertyOverrides.get(def.getName()); + if (override == null) + { + inheritedProperties.put(def.getName(), def); + } + else + { + inheritedProperties.put( + def.getName(), + new M2PropertyDefinition(this, def, override, prefixResolver, modelConstraints)); + } + } + } + + // Append list of defined properties + for (PropertyDefinition def : properties.values()) + { + if (inheritedProperties.containsKey(def.getName())) + { + throw new DuplicateDefinitionException(ERR_DUPLICATE_PROPERTY_IN_CLASS_HIERARCHY, def.getName().toPrefixString(), name.toPrefixString()); + } + inheritedProperties.put(def.getName(), def); + } + + // Build list of inherited associations + if (parentClass != null) + { + inheritedAssociations.putAll(parentClass.getAssociations()); + } + + // Append list of defined associations + for (AssociationDefinition def : associations.values()) + { + if (inheritedAssociations.containsKey(def.getName())) + { + throw new DuplicateDefinitionException(ERR_DUPLICATE_ASSOCIATION_IN_CLASS_HIERARCHY, def.getName().toPrefixString(), name.toPrefixString()); + } + inheritedAssociations.put(def.getName(), def); + } + + // Derive Child Associations + for (AssociationDefinition def : inheritedAssociations.values()) + { + if (def instanceof ChildAssociationDefinition) + { + inheritedChildAssociations.put(def.getName(), (ChildAssociationDefinition)def); + } + } + + // Build list of inherited default aspects + if (parentClass != null) + { + inheritedDefaultAspects.addAll(parentClass.getDefaultAspects()); + } + + // Append list of defined default aspects + for (AspectDefinition def : defaultAspects) + { + if (!inheritedDefaultAspects.contains(def)) + { + inheritedDefaultAspects.add(def); + } + } + + // Convert to set of names + for (AspectDefinition aspDef : inheritedDefaultAspects) + { + inheritedDefaultAspectNames.add(aspDef.getName()); + } + + // resolve archive inheritance + if (parentClass != null && archive == null) + { + // archive not explicitly set on this class and there is a parent class + inheritedArchive = ((M2ClassDefinition)parentClass).getArchive(); + } + + // resolve includedInSuperTypeQuery inheritance + if (parentClass != null && includedInSuperTypeQuery == null) + { + // archive not explicitly set on this class and there is a parent class + inheritedIncludedInSuperTypeQuery = ((M2ClassDefinition)parentClass).getIncludedInSuperTypeQuery(); + } + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getModel() + */ + public ModelDefinition getModel() + { + return model; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#getName() + */ + public QName getName() + { + return name; + } + + @Override + public String getDescription() + { + return getDescription(staticMessageLookup); + } + + @Override + public String getTitle() + { + return getTitle(staticMessageLookup); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#getTitle() + */ + public String getTitle(MessageLookup messageLookup) + { + String value = M2Label.getLabel(model, messageLookup, "class", name, "title"); + if (value == null) + { + value = m2Class.getTitle(); + } + return value; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#getDescription() + */ + public String getDescription(MessageLookup messageLookup) + { + String value = M2Label.getLabel(model, messageLookup, "class", name, "description"); + if (value == null) + { + value = m2Class.getDescription(); + } + return value; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#getParentName() + */ + public QName getParentName() + { + return parentName; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#isAspect() + */ + public boolean isAspect() + { + return (m2Class instanceof M2Aspect); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getArchive() + */ + public Boolean getArchive() + { + return archive == null ? inheritedArchive : archive; + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#includedInSuperTypeQuery() + */ + public Boolean getIncludedInSuperTypeQuery() + { + if(includedInSuperTypeQuery != null) + { + return includedInSuperTypeQuery; + } + if(inheritedIncludedInSuperTypeQuery != null) + { + return inheritedIncludedInSuperTypeQuery; + } + return Boolean.TRUE; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#getProperties() + */ + public Map getProperties() + { + return Collections.unmodifiableMap(inheritedProperties); + } + + /** + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getDefaultValues() + */ + public Map getDefaultValues() + { + Map result = new HashMap(5); + + for(Map.Entry entry : inheritedProperties.entrySet()) + { + PropertyDefinition propertyDefinition = entry.getValue(); + String defaultValue = propertyDefinition.getDefaultValue(); + if (defaultValue != null) + { + result.put(entry.getKey(), defaultValue); + } + } + + return Collections.unmodifiableMap(result); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#getAssociations() + */ + public Map getAssociations() + { + return Collections.unmodifiableMap(inheritedAssociations); + } + + /** + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getDefaultAspects() + */ + public List getDefaultAspects() + { + return inheritedDefaultAspects; + } + + /** + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getDefaultAspects(boolean) + */ + public List getDefaultAspects(boolean inherited) + { + return inherited ? getDefaultAspects() : defaultAspects; + } + + /** + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getDefaultAspectNames() + */ + public Set getDefaultAspectNames() + { + return inheritedDefaultAspectNames; + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#isContainer() + */ + public boolean isContainer() + { + return !inheritedChildAssociations.isEmpty(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ClassDefinition#getChildAssociations() + */ + public Map getChildAssociations() + { + return Collections.unmodifiableMap(inheritedChildAssociations); + } + + @Override + public int hashCode() + { + return name.hashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (!(obj instanceof M2ClassDefinition)) + { + return false; + } + return name.equals(((M2ClassDefinition)obj).name); + } + + /** + * return differences in class definition + * + * note: + * - checks properties for incremental updates, but does not include the diffs + * - checks assocs & child assocs for incremental updates, but does not include the diffs + * - incremental updates include changes in title/description, property default value, etc + */ + /* package */ List diffClass(ClassDefinition classDef) + { + List modelDiffs = new ArrayList(); + boolean isUpdated = false; + boolean isUpdatedIncrementally = false; + + if (this == classDef) + { + return modelDiffs; + } + + // check name - cannot be null + if (! getName().equals(classDef.getName())) + { + isUpdated = true; + } + + // check title + if (! EqualsHelper.nullSafeEquals(getTitle(null), classDef.getTitle(null), false)) + { + isUpdatedIncrementally = true; + } + + // check description + if (! EqualsHelper.nullSafeEquals(getDescription(null), classDef.getDescription(null), false)) + { + isUpdatedIncrementally = true; + } + + // check parent name + if (getParentName() != null) + { + if (! getParentName().equals(classDef.getParentName())) + { + isUpdated = true; + } + } + else if (classDef.getParentName() != null) + { + isUpdated = true; + } + + // check if aspect (or type) + if (isAspect() != classDef.isAspect()) + { + isUpdated = true; + } + + // check if container + if (isContainer() != classDef.isContainer()) + { + if (isContainer()) + { + // updated (non-incrementally) if class was a container and now is not a container - ie. all child associations removed + isUpdated = true; + } + + if (classDef.isContainer()) + { + // updated incrementally if class was not a container and now is a container - ie. some child associations added + isUpdatedIncrementally = true; + } + } + + // check all properties (including inherited properties) + Collection propertyDiffs = M2PropertyDefinition.diffPropertyLists(getProperties().values(), classDef.getProperties().values()); + + modelDiffs.addAll(propertyDiffs); + + // check all associations (including inherited associations, child associations and inherited child associations) + Collection assocDiffs = M2AssociationDefinition.diffAssocLists(getAssociations().values(), classDef.getAssociations().values()); + + modelDiffs.addAll(assocDiffs); + + // check default/mandatory aspects + for (AspectDefinition newAspect : classDef.getDefaultAspects(false)) + { + boolean found = false; + for (AspectDefinition previousAspect : getDefaultAspects(false)) + { + if (newAspect.getName().equals(previousAspect.getName())) + { + found = true; + break; + } + } + + if (! found) + { + // mandatory aspect added (to aspect or type) + isUpdated = true; + } + } + + // check archive/inheritedArchive + if (getArchive() == null) + { + if (classDef.getArchive() != null) + { + isUpdatedIncrementally = true; + } + } + else + { + Boolean classArchive = classDef.getArchive(); + if (classArchive == null || classArchive.booleanValue() != getArchive().booleanValue()) + { + isUpdatedIncrementally = true; + } + } + + // check includedInSuperTypeQuery/inheritedIncludedInSuperTypeQuery + if (getIncludedInSuperTypeQuery() == null) + { + // belts-and-braces (currently does not return null) + if (classDef.getIncludedInSuperTypeQuery() != null) + { + isUpdatedIncrementally = true; + } + } + else + { + Boolean classIncludedInSuperTypeQuery = classDef.getIncludedInSuperTypeQuery(); + if (classIncludedInSuperTypeQuery == null || classIncludedInSuperTypeQuery.booleanValue() != getIncludedInSuperTypeQuery().booleanValue()) + { + isUpdatedIncrementally = true; + } + } + + String modelDiffType; + if (isAspect()) + { + modelDiffType = M2ModelDiff.TYPE_ASPECT; + } + else + { + modelDiffType = M2ModelDiff.TYPE_TYPE; + } + + if (isUpdated) + { + modelDiffs.add(new M2ModelDiff(name, modelDiffType, M2ModelDiff.DIFF_UPDATED)); + } + else if (isUpdatedIncrementally) + { + modelDiffs.add(new M2ModelDiff(name, modelDiffType, M2ModelDiff.DIFF_UPDATED_INC)); + } + else + { + modelDiffs.add(new M2ModelDiff(name, modelDiffType, M2ModelDiff.DIFF_UNCHANGED)); + } + + return modelDiffs; + } + + /** + * return differences in class definition lists + * + */ + /*package*/ static List diffClassLists(Collection previousClasses, Collection newClasses, String M2ModelDiffType) + { + List modelDiffs = new ArrayList(); + + for (ClassDefinition previousClass : previousClasses) + { + boolean found = false; + for (ClassDefinition newClass : newClasses) + { + if (newClass.getName().equals(previousClass.getName())) + { + modelDiffs.addAll(((M2ClassDefinition)previousClass).diffClass(newClass)); + found = true; + break; + } + } + + if (! found) + { + modelDiffs.add(new M2ModelDiff(previousClass.getName(), M2ModelDiffType, M2ModelDiff.DIFF_DELETED)); + } + } + + for (ClassDefinition newClass : newClasses) + { + boolean found = false; + for (ClassDefinition previousClass : previousClasses) + { + if (newClass.getName().equals(previousClass.getName())) + { + found = true; + break; + } + } + + if (! found) + { + modelDiffs.add(new M2ModelDiff(newClass.getName(), M2ModelDiffType, M2ModelDiff.DIFF_CREATED)); + } + } + + return modelDiffs; + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getAnalyserResourceBundleName() + */ + @Override + public String getAnalyserResourceBundleName() + { + return analyserResourceBundleName; + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getParentClassDefinition() + */ + @Override + public ClassDefinition getParentClassDefinition() + { + return parentClassDefinition; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2Constraint.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Constraint.java new file mode 100644 index 0000000000..11f8082753 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Constraint.java @@ -0,0 +1,139 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.ArrayList; +import java.util.List; + +/** + * Abstract Property Constraint. + * + * @author Derek Hulley + */ +public class M2Constraint +{ + private String name; + private String ref; + private String type; + private String title; + private String description; + private List parameters = new ArrayList(2); + + /*package*/ M2Constraint() + { + } + + @Override + public String toString() + { + return this.name; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getRef() + { + return ref; + } + + public void setRef(String refName) + { + this.ref = refName; + } + + public String getType() + { + return type; + } + + public void setType(String type) + { + this.type = type; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public List getParameters() + { + return parameters; + } + + public M2NamedValue createParameter(String name, String simpleValue) + { + M2NamedValue param = new M2NamedValue(); + param.setName(name); + param.setSimpleValue(simpleValue); + parameters.add(param); + return param; + } + + public M2NamedValue createParameter(String name, List listValue) + { + M2NamedValue param = new M2NamedValue(); + param.setName(name); + param.setListValue(listValue); + parameters.add(param); + return param; + } + + public void removeParameter(String name) + { + List params = new ArrayList(getParameters()); + for (M2NamedValue param : params) + { + if (param.getName().equals(name)) + { + parameters.remove(param); + } + } + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2ConstraintDefinition.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2ConstraintDefinition.java new file mode 100644 index 0000000000..10da726728 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2ConstraintDefinition.java @@ -0,0 +1,523 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.alfresco.repo.dictionary.constraint.ListOfValuesConstraint; +import org.alfresco.repo.dictionary.constraint.NumericRangeConstraint; +import org.alfresco.repo.dictionary.constraint.RegexConstraint; +import org.alfresco.repo.dictionary.constraint.RegisteredConstraint; +import org.alfresco.repo.dictionary.constraint.StringLengthConstraint; +import org.alfresco.repo.i18n.StaticMessageLookup; +import org.alfresco.service.cmr.dictionary.Constraint; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.EqualsHelper; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.beans.InvalidPropertyException; +import org.springframework.beans.PropertyAccessException; + +/** + * Compiled Property Constraint + * + * @author Derek Hulley. janv + */ +/* package */class M2ConstraintDefinition implements ConstraintDefinition +{ + private static final String PROP_SHORT_NAME = "shortName"; + private static final String PROP_TITLE = "title"; + private static final String PROP_DESCRIPTION = "description"; + + public static final String ERR_CYCLIC_REF = "d_dictionary.constraint.err.cyclic_ref"; + public static final String ERR_TYPE_AND_REF = "d_dictionary.constraint.err.type_and_ref"; + public static final String ERR_TYPE_OR_REF = "d_dictionary.constraint.err.type_or_ref"; + public static final String ERR_REF_NOT_FOUND = "d_dictionary.constraint.err.ref_not_found"; + public static final String ERR_ANON_NEEDS_PROPERTY = "d_dictionary.constraint.err.anon_needs_property"; + public static final String ERR_INVALID_TYPE = "d_dictionary.constraint.err.invalid_type"; + public static final String ERR_SIMPLE_AND_LIST = "d_dictionary.constraint.err.property_simple_and_list"; + public static final String ERR_CONSTRUCT_FAILURE = "d_dictionary.constraint.err.construct_failure"; + public static final String ERR_PROPERTY_MISMATCH = "d_dictionary.constraint.err.property_mismatch"; + public static final String ERR_RESERVED_PROPERTY = "d_dictionary.constraint.err.reserved_property"; + public static final String ERR_NAMESPACE_NOT_DEFINED = "d_dictionary.constraint.err.namespace_not_defined"; + + private static int anonPropCount = 0; + + private ModelDefinition model; + private NamespacePrefixResolver prefixResolver; + private M2Constraint m2Constraint; + private QName name; + private Constraint constraint; + private boolean resolving; + private transient MessageLookup staticMessageLookup = new StaticMessageLookup(); + + /* package */M2ConstraintDefinition(M2PropertyDefinition m2PropertyDef, M2Constraint m2Constraint, + NamespacePrefixResolver prefixResolver) + { + this(m2PropertyDef.getModel(), m2PropertyDef, m2Constraint, prefixResolver); + } + + /* package */M2ConstraintDefinition(ModelDefinition modelDefinition, M2PropertyDefinition m2PropertyDef, + M2Constraint m2Constraint, NamespacePrefixResolver prefixResolver) + { + this.model = modelDefinition; + this.m2Constraint = m2Constraint; + this.prefixResolver = prefixResolver; + + String constraintName = m2Constraint.getName(); + if (constraintName == null) + { + // the constraint is anonymous, so it has to be defined within the context of a property + if (m2PropertyDef == null) + { + throw new DictionaryException(ERR_ANON_NEEDS_PROPERTY); + } + // pick the name up from the property and some anonymous value + String localName = m2PropertyDef.getName().getLocalName() + "_anon_" + (++anonPropCount); + this.name = QName.createQName(m2PropertyDef.getName().getNamespaceURI(), localName); + m2Constraint.setName(this.name.getPrefixedQName(prefixResolver).toPrefixString()); + } + else + { + this.name = QName.createQName(m2Constraint.getName(), prefixResolver); + if (!model.isNamespaceDefined(name.getNamespaceURI())) + { + throw new DictionaryException(ERR_NAMESPACE_NOT_DEFINED, name.toPrefixString(), name.getNamespaceURI(), model.getName().toPrefixString()); + } + } + } + + /* package */synchronized void resolveDependencies(ModelQuery query, boolean enableConstraintClassLoading) + { + if (resolving) + { + throw new DictionaryException(ERR_CYCLIC_REF, name.toPrefixString()); + } + // prevent circular references + try + { + resolving = true; + resolveInternal(query, enableConstraintClassLoading); + } + finally + { + resolving = false; + } + } + + private synchronized void resolveInternal(ModelQuery query, boolean enableConstraintClassLoading) + { + if (constraint != null) + { + // already been resolved + return; + } + + String shortName = name.toPrefixString(); + String ref = m2Constraint.getRef(); + String type = m2Constraint.getType(); + + String title = m2Constraint.getTitle(); + String description = m2Constraint.getDescription(); + + if (ref != null && type != null) + { + throw new DictionaryException(ERR_TYPE_AND_REF, shortName); + } + else if (ref == null && type == null) + { + throw new DictionaryException(ERR_TYPE_OR_REF, shortName); + } + else if (ref != null) + { + // resolve the reference name + QName qnameRef = QName.createQName(ref, prefixResolver); + // ensure that the reference exists in the model + M2ConstraintDefinition constraintDef = (M2ConstraintDefinition) query.getConstraint(qnameRef); + if (constraintDef == null) + { + throw new DictionaryException(ERR_REF_NOT_FOUND, ref, shortName); + } + // make sure that the constraint definition has itself been resolved + constraintDef.resolveDependencies(query, enableConstraintClassLoading); + // just use the constraint provided by the referenced definition + this.constraint = constraintDef.getConstraint(); + + //use real constraint name instead of anonymous name + //TODO Fix backed out - breaks DictionaryDAOTest + //this.name = constraintDef.getName(); + + + if (m2Constraint.getTitle() == null) + { + m2Constraint.setTitle(constraintDef.getTitle(null)); + } + + if (m2Constraint.getDescription() == null) + { + m2Constraint.setDescription(constraintDef.getDescription(null)); + } + } + else + { + // we have to build the constraint from the type + try + { + ConstraintType constraintType = ConstraintType.valueOf(type); + constraint = constraintType.newInstance(); + } + catch (IllegalArgumentException e) + { + // try to establish it as a class + try + { + if(enableConstraintClassLoading) + { + @SuppressWarnings("unchecked") + Class clazz = Class.forName(type); + constraint = (Constraint) clazz.newInstance(); + } + } + catch (ClassNotFoundException ee) + { + throw new DictionaryException(ERR_INVALID_TYPE, type, shortName); + } + catch (ClassCastException ee) + { + throw new DictionaryException(ERR_INVALID_TYPE, type, shortName); + } + catch (Exception ee) + { + throw new DictionaryException(ERR_CONSTRUCT_FAILURE, type, shortName); + } + } + + if(constraint != null) + { + // property setters + BeanWrapper beanWrapper = new BeanWrapperImpl(constraint); + List constraintNamedValues = m2Constraint.getParameters(); + + if (constraintNamedValues != null) + { + for (M2NamedValue namedValue : constraintNamedValues) + { + String namedValueName = namedValue.getName(); + // Check for reserved properties + if (namedValueName.equals(PROP_SHORT_NAME)) + { + throw new DictionaryException(ERR_RESERVED_PROPERTY, PROP_SHORT_NAME, namedValueName); + } + + Object value = null; + if (namedValue.getSimpleValue() != null && namedValue.getListValue() != null) + { + throw new DictionaryException(ERR_SIMPLE_AND_LIST, shortName, namedValue.getName()); + } + else if (namedValue.getSimpleValue() != null) + { + value = namedValue.getSimpleValue(); + } + else if (namedValue.getListValue() != null) + { + value = namedValue.getListValue(); + } + try + { + beanWrapper.setPropertyValue(namedValueName, value); + } + catch (PropertyAccessException e) + { + throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, namedValueName, shortName); + } + catch (InvalidPropertyException e) + { + throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, namedValueName, shortName); + } + } + + // Pass in the short name as a special property, if it is available + if (beanWrapper.isWritableProperty(PROP_SHORT_NAME)) + { + try + { + beanWrapper.setPropertyValue(PROP_SHORT_NAME, shortName); + } + catch (PropertyAccessException e) + { + throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, shortName, shortName); + } + catch (InvalidPropertyException e) + { + throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, shortName, shortName); + } + } + + if ((title != null) && (beanWrapper.isWritableProperty(PROP_TITLE))) + { + beanWrapper.setPropertyValue(PROP_TITLE, title); + } + + if ((title != null) && (beanWrapper.isWritableProperty(PROP_DESCRIPTION))) + { + beanWrapper.setPropertyValue(PROP_DESCRIPTION, description); + } + } + + // now initialize + constraint.initialize(); + } + } + } + + /** + * @see #getName() + */ + @Override + public String toString() + { + return getName().toString(); + } + + @Override + public ModelDefinition getModel() + { + return model; + } + + @Override + public QName getName() + { + return name; + } + + @Override + public String getTitle() + { + return getTitle(staticMessageLookup); + } + + @Override + public String getDescription() + { + return getDescription(staticMessageLookup); + } + + @Override + public String getTitle(MessageLookup messageLookup) + { + String value = M2Label.getLabel(model, messageLookup, "constraint", name, "title"); + if (value == null) + { + value = m2Constraint.getTitle(); + } + return value; + } + + @Override + public String getDescription(MessageLookup messageLookup) + { + String value = M2Label.getLabel(model, messageLookup, "constraint", name, "description"); + if (value == null) + { + value = m2Constraint.getDescription(); + } + return value; + } + + @Override + public Constraint getConstraint() + { + return constraint; + } + + @Override + public QName getRef() + { + QName refQName = null; + String ref = m2Constraint.getRef(); + if (ref != null) + { + refQName = QName.createQName(ref, prefixResolver); + } + return refQName; + } + + /** + * Well-known constraint types + */ + public static enum ConstraintType + { + REGISTERED + { + @Override + protected Constraint newInstance() + { + return new RegisteredConstraint(); + } + }, + REGEX + { + @Override + protected Constraint newInstance() + { + return new RegexConstraint(); + } + }, + MINMAX + { + @Override + protected Constraint newInstance() + { + return new NumericRangeConstraint(); + } + }, + LENGTH + { + @Override + protected Constraint newInstance() + { + return new StringLengthConstraint(); + } + }, + LIST + { + @Override + protected Constraint newInstance() + { + return new ListOfValuesConstraint(); + } + }; + + /** + * @return Returns the constraint implementation + */ + protected abstract Constraint newInstance(); + } + + /* package */ M2ModelDiff diffConstraint(ConstraintDefinition conDef) + { + M2ModelDiff modelDiff = null; + boolean isUpdated = false; + boolean isUpdatedIncrementally = false; + + if (this == conDef) + { + modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_CONSTRAINT, M2ModelDiff.DIFF_UNCHANGED); + return modelDiff; + } + + // check name - cannot be null + if (! name.equals(conDef.getName())) + { + isUpdated = true; + } + + // check title + if (! EqualsHelper.nullSafeEquals(getTitle(null), conDef.getTitle(null), false)) + { + isUpdatedIncrementally = true; + } + + // check description + if (! EqualsHelper.nullSafeEquals(getDescription(null), conDef.getDescription(null), false)) + { + isUpdatedIncrementally = true; + } + + // check type string + if (! EqualsHelper.nullSafeEquals(getConstraint().getType(), conDef.getConstraint().getType())) + { + isUpdated = true; + } + + if (isUpdated) + { + modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_CONSTRAINT, M2ModelDiff.DIFF_UPDATED); + } + else if (isUpdatedIncrementally) + { + modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_CONSTRAINT, M2ModelDiff.DIFF_UPDATED_INC); + } + else + { + modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_CONSTRAINT, M2ModelDiff.DIFF_UNCHANGED); + } + + return modelDiff; + } + + /*package*/ static Collection diffConstraintLists(Collection previousConstraints, Collection newConstraints) + { + List modelDiffs = new ArrayList(); + + for (ConstraintDefinition previousConstraint : previousConstraints) + { + boolean found = false; + for (ConstraintDefinition newConstraint : newConstraints) + { + if (newConstraint.getName().equals(previousConstraint.getName())) + { + modelDiffs.add(((M2ConstraintDefinition)previousConstraint).diffConstraint(previousConstraint)); + found = true; + break; + } + } + + if (! found) + { + modelDiffs.add(new M2ModelDiff(previousConstraint.getName(), M2ModelDiff.TYPE_CONSTRAINT, M2ModelDiff.DIFF_DELETED)); + } + } + + for (ConstraintDefinition newConstraint : newConstraints) + { + boolean found = false; + for (ConstraintDefinition previousConstraint : previousConstraints) + { + if (newConstraint.getName().equals(previousConstraint.getName())) + { + found = true; + break; + } + } + + if (! found) + { + modelDiffs.add(new M2ModelDiff(newConstraint.getName(), M2ModelDiff.TYPE_CONSTRAINT, M2ModelDiff.DIFF_CREATED)); + } + } + + return modelDiffs; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2DataType.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2DataType.java new file mode 100644 index 0000000000..4f6104aecc --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2DataType.java @@ -0,0 +1,125 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + + +/** + * Property Type Definition + * + * @author David Caruana + * + */ +public class M2DataType +{ + private String name = null; + private String title = null; + private String description = null; + private String defaultAnalyserClassName = null; + private String javaClassName = null; + private String analyserResourceBundleName = null; + + + /*package*/ M2DataType() + { + super(); + } + + + public String getName() + { + return name; + } + + + public void setName(String name) + { + this.name = name; + } + + + public String getTitle() + { + return title; + } + + + public void setTitle(String title) + { + this.title = title; + } + + + public String getDescription() + { + return description; + } + + + public void setDescription(String description) + { + this.description = description; + } + + + public String getDefaultAnalyserClassName() + { + return defaultAnalyserClassName; + } + + + public void setDefaultAnalyserClassName(String defaultAnalyserClassName) + { + this.defaultAnalyserClassName = defaultAnalyserClassName;; + } + + + public String getJavaClassName() + { + return javaClassName; + } + + + public void setJavaClassName(String javaClassName) + { + this.javaClassName = javaClassName;; + } + + + /** + * @return String + */ + public String getAnalyserResourceBundleName() + { + return analyserResourceBundleName; + } + + + public void setAnalyserResourceBundleName(String analyserResourceBundleName) + { + this.analyserResourceBundleName = analyserResourceBundleName; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2DataTypeDefinition.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2DataTypeDefinition.java new file mode 100644 index 0000000000..bc72b140de --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2DataTypeDefinition.java @@ -0,0 +1,253 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.Locale; +import java.util.ResourceBundle; + +import org.springframework.extensions.surf.util.I18NUtil; +import org.springframework.util.StringUtils; +import org.alfresco.repo.i18n.StaticMessageLookup; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; + + +/** + * Compiled Property Type Definition + * + * @author David Caruana + * + */ +/*package*/ class M2DataTypeDefinition implements DataTypeDefinition +{ + private static final String ERR_NOT_DEFINED_NAMESPACE = "d_dictionary.data_type.namespace_not_defined"; + private static final String ERR_JAVA_CLASS_NOT_SPECIFIED = "d_dictionary.data_type.java_class_not_specified"; + private static final String ERR_JAVA_CLASS_INVALID = "d_dictionary.data_type.java_class_invalid"; + + private ModelDefinition model; + private QName name; + private M2DataType dataType; + private String analyserResourceBundleName; + private transient MessageLookup staticMessageLookup = new StaticMessageLookup(); + + + /*package*/ M2DataTypeDefinition(ModelDefinition model, M2DataType propertyType, NamespacePrefixResolver resolver) + { + this.model = model; + this.name = QName.createQName(propertyType.getName(), resolver); + if (!model.isNamespaceDefined(name.getNamespaceURI())) + { + throw new DictionaryException(ERR_NOT_DEFINED_NAMESPACE, name.toPrefixString(), name.getNamespaceURI(), model.getName().toPrefixString()); + } + this.dataType = propertyType; + this.analyserResourceBundleName = dataType.getAnalyserResourceBundleName(); + } + + + /*package*/ void resolveDependencies(ModelQuery query) + { + // Ensure java class has been specified + String javaClass = dataType.getJavaClassName(); + if (javaClass == null) + { + throw new DictionaryException(ERR_JAVA_CLASS_NOT_SPECIFIED, name.toPrefixString()); + } + + // Ensure java class is valid and referenceable + try + { + Class.forName(javaClass); + } + catch (ClassNotFoundException e) + { + throw new DictionaryException(ERR_JAVA_CLASS_INVALID, javaClass, name.toPrefixString(), e); + } + } + + /** + * @see #getName() + */ + @Override + public String toString() + { + return getName().toString(); + } + + @Override + public ModelDefinition getModel() + { + return model; + } + + @Override + public QName getName() + { + return name; + } + + @Override + public String getTitle() + { + return getTitle(staticMessageLookup); + } + + @Override + public String getDescription() + { + return getDescription(staticMessageLookup); + } + + @Override + public String getTitle(MessageLookup messageLookup) + { + String value = M2Label.getLabel(model, messageLookup, "datatype", name, "title"); + if (value == null) + { + value = dataType.getTitle(); + } + return value; + } + + @Override + public String getDescription(MessageLookup messageLookup) + { + String value = M2Label.getLabel(model, messageLookup, "datatype", name, "description"); + if (value == null) + { + value = dataType.getDescription(); + } + return value; + } + + @Override + public String getDefaultAnalyserClassName() + { + return dataType.getDefaultAnalyserClassName(); + } + + @Override + public String getJavaClassName() + { + return dataType.getJavaClassName(); + } + + @Override + public String getAnalyserResourceBundleName() + { + return analyserResourceBundleName; + } + + @Override + public String resolveAnalyserClassName() + { + return resolveAnalyserClassName(I18NUtil.getLocale()); + } + + /** + * @param locale Locale + * @return String + */ + @Override + public String resolveAnalyserClassName(Locale locale) + { + ClassLoader resourceBundleClassLoader = getModel().getDictionaryDAO().getResourceClassLoader(); + if(resourceBundleClassLoader == null) + { + resourceBundleClassLoader = this.getClass().getClassLoader(); + } + + StringBuilder keyBuilder = new StringBuilder(64); + keyBuilder.append(getModel().getName().toPrefixString()); + keyBuilder.append(".datatype"); + keyBuilder.append(".").append(getName().toPrefixString()); + keyBuilder.append(".analyzer"); + String key = StringUtils.replace(keyBuilder.toString(), ":", "_"); + + String analyserClassName = null; + + String defaultAnalyserResourceBundleName = this.getModel().getDictionaryDAO().getDefaultAnalyserResourceBundleName(); + if(defaultAnalyserResourceBundleName != null) + { + ResourceBundle bundle = ResourceBundle.getBundle(defaultAnalyserResourceBundleName, locale, resourceBundleClassLoader); + if(bundle.containsKey(key)) + { + analyserClassName = bundle.getString(key); + } + } + + String analyserResourceBundleName; + if(analyserClassName == null) + { + analyserResourceBundleName = dataType.getAnalyserResourceBundleName(); + if(analyserResourceBundleName != null) + { + ResourceBundle bundle = ResourceBundle.getBundle(analyserResourceBundleName, locale, resourceBundleClassLoader); + if(bundle.containsKey(key)) + { + analyserClassName = bundle.getString(key); + } + } + } + + if(analyserClassName == null) + { + analyserResourceBundleName = getModel().getAnalyserResourceBundleName(); + if(analyserResourceBundleName != null) + { + ResourceBundle bundle = ResourceBundle.getBundle(analyserResourceBundleName, locale, resourceBundleClassLoader); + if(bundle.containsKey(key)) + { + analyserClassName = bundle.getString(key); + } + } + } + + if(analyserClassName == null) + { + // MLTEXT should fall back to TEXT for analysis + if(name.equals(DataTypeDefinition.MLTEXT)) + { + analyserClassName = model.getDictionaryDAO().getDataType(DataTypeDefinition.TEXT).resolveAnalyserClassName(locale); + if(analyserClassName == null) + { + analyserClassName = dataType.getDefaultAnalyserClassName(); + } + } + else + { + analyserClassName = dataType.getDefaultAnalyserClassName(); + } + } + + return analyserClassName; + } + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2Label.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Label.java new file mode 100644 index 0000000000..e206ea296c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Label.java @@ -0,0 +1,91 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.Locale; + +import org.springframework.extensions.surf.util.I18NUtil; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.QName; +import org.springframework.util.StringUtils; + + +/** + * Helper for obtaining display labels for data dictionary items + * + * @author David Caruana + */ +public class M2Label +{ + + /** + * Get label for data dictionary item given specified locale + * + * @param locale Locale + * @param model ModelDefinition + * @param messageLookup MessageLookup + * @param type String + * @param item QName + * @param label String + * @return String + */ + public static String getLabel(Locale locale, ModelDefinition model, MessageLookup messageLookup, String type, QName item, String label) + { + if (messageLookup == null) + { + return null; + } + String key = model.getName().toPrefixString(); + if (type != null) + { + key += "." + type; + } + if (item != null) + { + key += "." + item.toPrefixString(); + } + key += "." + label; + key = StringUtils.replace(key, ":", "_"); + return messageLookup.getMessage(key, locale); + } + + /** + * Get label for data dictionary item + * + * @param model ModelDefinition + * @param messageLookup MessageLookup + * @param type String + * @param item QName + * @param label String + * @return String + */ + public static String getLabel(ModelDefinition model, MessageLookup messageLookup, String type, QName item, String label) + { + return getLabel(I18NUtil.getLocale(), model, messageLookup, type, item, label); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2Model.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Model.java new file mode 100644 index 0000000000..e11862b116 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Model.java @@ -0,0 +1,505 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Properties; +import java.util.zip.CRC32; + +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.jibx.runtime.BindingDirectory; +import org.jibx.runtime.IBindingFactory; +import org.jibx.runtime.IMarshallingContext; +import org.jibx.runtime.IUnmarshallingContext; +import org.jibx.runtime.JiBXException; + + +/** + * Model Definition. + * + * @author David Caruana + * + */ +public class M2Model +{ + private static final String ERR_PARSE_FAILURE = "d_dictionary.model.err.parse.failure"; + private static final String ERR_CREATE_M2MODEL_FAILURE = "d_dictionary.model.err.create_m2model.failure"; + + private String name = null; + private String description = null; + private String author = null; + private Date published = null; + private String version; + private String analyserResourceBundleName = null; + + private List namespaces = new ArrayList(); + private List imports = new ArrayList(); + private List dataTypes = new ArrayList(); + private List types = new ArrayList(); + private List aspects = new ArrayList(); + private List constraints = new ArrayList(); + + private M2Model() + { + } + + + /** + * Construct an empty model + * + * @param name the name of the model + * @return the model + */ + public static M2Model createModel(String name) + { + M2Model model = new M2Model(); + model.name = name; + return model; + } + + + /** + * Construct a model from a dictionary xml specification + * + * @param xml the dictionary xml + * @return the model representation of the xml + */ + public static M2Model createModel(InputStream xml) + { + return createModel("default", xml); + } + + public static M2Model createModel(String bindingName, InputStream xml) + { + try + { + IBindingFactory factory = BindingDirectory.getFactory(bindingName, M2Model.class); + IUnmarshallingContext context = factory.createUnmarshallingContext(); + Object obj = context.unmarshalDocument(xml, null); + return (M2Model)obj; + } + catch(JiBXException e) + { + throw new DictionaryException(ERR_PARSE_FAILURE, e); + } + } + + + /** + * Render the model to dictionary XML + * + * @param xml the dictionary xml representation of the model + */ + public void toXML(OutputStream xml) + { + toXML(null, xml); + } + + public void toXML(ModelDefinition.XMLBindingType bindingType, OutputStream xml) + { + try + { + if(bindingType == null) + { + bindingType = ModelDefinition.XMLBindingType.DEFAULT; + } + + String bindingName = bindingType.toString(); + IBindingFactory factory = (bindingName != null) ? BindingDirectory.getFactory(bindingName, M2Model.class) : + BindingDirectory.getFactory("default", M2Model.class); + IMarshallingContext context = factory.createMarshallingContext(); + context.setIndent(4); + context.marshalDocument(this, "UTF-8", null, xml); + } + catch(JiBXException e) + { + throw new DictionaryException(ERR_CREATE_M2MODEL_FAILURE, e); + } + } + + public long getChecksum(ModelDefinition.XMLBindingType bindingType) + { + final CRC32 crc = new CRC32(); + + // construct the crc directly from the model's xml stream + toXML(bindingType, new OutputStream() { + public void write(int b) throws IOException + { + crc.update(b); + } + }); + + return crc.getValue(); + } + + /** + * Create a compiled form of this model + * + * @param dictionaryDAO dictionary DAO + * @param namespaceDAO namespace DAO + * @return the compiled form of the model + */ + public CompiledModel compile(DictionaryDAO dictionaryDAO, NamespaceDAO namespaceDAO, boolean enableConstraintClassLoading) + { + CompiledModel compiledModel = new CompiledModel(this, dictionaryDAO, namespaceDAO, enableConstraintClassLoading); + return compiledModel; + } + + + public String getName() + { + return name; + } + + + public void setName(String name) + { + this.name = name; + } + + + public String getDescription() + { + return description; + } + + + public void setDescription(String description) + { + this.description = description; + } + + + public String getAuthor() + { + return author; + } + + + public void setAuthor(String author) + { + this.author = author; + } + + + public Date getPublishedDate() + { + return published; + } + + + public void setPublishedDate(Date published) + { + this.published = published; + } + + + public String getVersion() + { + return version; + } + + + public void setVersion(String version) + { + this.version = version; + } + + + public M2Type createType(String name) + { + M2Type type = new M2Type(); + type.setName(name); + types.add(type); + return type; + } + + + public void removeType(String name) + { + M2Type type = getType(name); + if (type != null) + { + types.remove(type); + } + } + + + public List getTypes() + { + return Collections.unmodifiableList(types); + } + + + public M2Type getType(String name) + { + for (M2Type candidate : types) + { + if (candidate.getName().equals(name)) + { + return candidate; + } + } + return null; + } + + + public M2Aspect createAspect(String name) + { + M2Aspect aspect = new M2Aspect(); + aspect.setName(name); + aspects.add(aspect); + return aspect; + } + + + public void removeAspect(String name) + { + M2Aspect aspect = getAspect(name); + if (aspect != null) + { + aspects.remove(aspect); + } + } + + + public List getAspects() + { + return Collections.unmodifiableList(aspects); + } + + + public M2Aspect getAspect(String name) + { + for (M2Aspect candidate : aspects) + { + if (candidate.getName().equals(name)) + { + return candidate; + } + } + return null; + } + + + public M2DataType createPropertyType(String name) + { + M2DataType type = new M2DataType(); + type.setName(name); + dataTypes.add(type); + return type; + } + + + public void removePropertyType(String name) + { + M2DataType type = getPropertyType(name); + if (type != null) + { + dataTypes.remove(name); + } + } + + + public List getPropertyTypes() + { + return Collections.unmodifiableList(dataTypes); + } + + + public M2DataType getPropertyType(String name) + { + for (M2DataType candidate : dataTypes) + { + if (candidate.getName().equals(name)) + { + return candidate; + } + } + return null; + } + + + public M2Namespace createNamespace(String uri, String prefix) + { + M2Namespace namespace = new M2Namespace(); + namespace.setUri(uri); + namespace.setPrefix(prefix); + namespaces.add(namespace); + return namespace; + } + + + public void removeNamespace(String uri) + { + M2Namespace namespace = getNamespace(uri); + if (namespace != null) + { + namespaces.remove(namespace); + } + } + + + public List getNamespaces() + { + return Collections.unmodifiableList(namespaces); + } + + + public M2Namespace getNamespace(String uri) + { + for (M2Namespace candidate : namespaces) + { + if (candidate.getUri().equals(uri)) + { + return candidate; + } + } + return null; + } + + + public M2Namespace createImport(String uri, String prefix) + { + M2Namespace namespace = new M2Namespace(); + namespace.setUri(uri); + namespace.setPrefix(prefix); + imports.add(namespace); + return namespace; + } + + + public void removeImport(String uri) + { + M2Namespace namespace = getImport(uri); + if (namespace != null) + { + imports.remove(namespace); + } + } + + + public List getImports() + { + return Collections.unmodifiableList(imports); + } + + + public M2Namespace getImport(String uri) + { + for (M2Namespace candidate : imports) + { + if (candidate.getUri().equals(uri)) + { + return candidate; + } + } + return null; + } + + public List getConstraints() + { + return Collections.unmodifiableList(constraints); + } + + public M2Constraint getConstraint(String name) + { + for (M2Constraint candidate : constraints) + { + if (candidate.getName().equals(name)) + { + return candidate; + } + } + return null; + } + + public M2Constraint createConstraint(String name, String type) + { + M2Constraint constraint = new M2Constraint(); + constraint.setName(name); + constraint.setType(type); + constraints.add(constraint); + return constraint; + } + + public void removeConstraint(String name) + { + M2Constraint constraint = getConstraint(name); + if (constraint != null) + { + constraints.remove(constraint); + } + } + + // Do not delete: referenced by m2binding.xml + @SuppressWarnings("unused") + private static List createList() + { + return new ArrayList(); + } + + + /** + * @return String + */ + public String getAnalyserResourceBundleName() + { + return analyserResourceBundleName; + } + + + public void setAnalyserResourceBundleName(String analyserResourceBundleName) + { + this.analyserResourceBundleName = analyserResourceBundleName; + } + + public void setConfigProperties(Properties configProperties) + { + if (types != null) + { + for (M2Class type : types) + { + type.setConfigProperties(configProperties); + } + } + if (aspects != null) + { + for (M2Class aspect : aspects) + { + aspect.setConfigProperties(configProperties); + } + } + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2ModelDefinition.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2ModelDefinition.java new file mode 100644 index 0000000000..a240743890 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2ModelDefinition.java @@ -0,0 +1,196 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; + +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.NamespaceDefinition; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; + +/** + * Compiled Model Definition + * + * @author David Caruana + * + */ +public class M2ModelDefinition implements ModelDefinition +{ + private QName name; + private M2Model model; + private String analyserResourceBundleName; + private DictionaryDAO dictionaryDAO; + + + /*package*/ M2ModelDefinition(M2Model model, NamespacePrefixResolver resolver, DictionaryDAO dictionaryDAO) + { + this.name = QName.createQName(model.getName(), resolver); + this.model = model; + this.analyserResourceBundleName = model.getAnalyserResourceBundleName(); + this.dictionaryDAO = dictionaryDAO; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ModelDefinition#getName() + */ + public QName getName() + { + return name; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ModelDefinition#getDescription() + */ + public String getDescription(MessageLookup messageLookup) + { + String value = M2Label.getLabel(this, messageLookup, null, null, "description"); + if (value == null) + { + value = model.getDescription(); + } + return value; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ModelDefinition#getAuthor() + */ + public String getAuthor() + { + return model.getAuthor(); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ModelDefinition#getPublishedDate() + */ + public Date getPublishedDate() + { + return model.getPublishedDate(); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.ModelDefinition#getVersion() + */ + public String getVersion() + { + return model.getVersion(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ModelDefinition#getNamespaces() + */ + public Collection getNamespaces() + { + List namespaces = new ArrayList(); + for (M2Namespace namespace : model.getNamespaces()) + { + namespaces.add(new M2NamespaceDefinition(this, namespace.getUri(), namespace.getPrefix())); + } + return namespaces; + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ModelDefinition#isNamespaceDefined(java.lang.String) + */ + public boolean isNamespaceDefined(String uri) + { + for (M2Namespace namespace : model.getNamespaces()) + { + if (namespace.getUri().equals(uri)) + { + return true; + } + } + return false; + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ModelDefinition#getImportedNamespaces() + */ + public Collection getImportedNamespaces() + { + List namespaces = new ArrayList(); + for (M2Namespace namespace : model.getImports()) + { + namespaces.add(new M2NamespaceDefinition(this, namespace.getUri(), namespace.getPrefix())); + } + return namespaces; + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ModelDefinition#isNamespaceImported(java.lang.String) + */ + public boolean isNamespaceImported(String uri) + { + for (M2Namespace namespace : model.getImports()) + { + if (namespace.getUri().equals(uri)) + { + return true; + } + } + return false; + } + + public void toXML(XMLBindingType bindingType, OutputStream xml) + { + model.toXML(bindingType, xml); + } + + public long getChecksum(XMLBindingType bindingType) + { + return model.getChecksum(bindingType); + } + + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.ModelDefinition#getAnalyserResourceBundleName() + */ + @Override + public String getAnalyserResourceBundleName() + { + return analyserResourceBundleName; + } + + + @Override + public DictionaryDAO getDictionaryDAO() + { + return dictionaryDAO; + } + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2ModelDiff.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2ModelDiff.java new file mode 100644 index 0000000000..d734b34d28 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2ModelDiff.java @@ -0,0 +1,131 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.service.cmr.dictionary.NamespaceDefinition; +import org.alfresco.service.namespace.QName; +import org.springframework.extensions.surf.util.ParameterCheck; + +/** + * Compiled Model Difference + * + * @author JanV + * + */ +public class M2ModelDiff +{ + public static final String DIFF_CREATED = "created"; + public static final String DIFF_UPDATED = "updated"; + public static final String DIFF_UPDATED_INC = "updated_inc"; // incremental update + public static final String DIFF_DELETED = "deleted"; + public static final String DIFF_UNCHANGED = "unchanged"; + + public static final String TYPE_TYPE = "TYPE"; + public static final String TYPE_ASPECT = "ASPECT"; + public static final String TYPE_DEFAULT_ASPECT = "DEFAULT_ASPECT"; + public static final String TYPE_PROPERTY = "PROPERTY"; + public static final String TYPE_ASSOCIATION = "ASSOCIATION"; + public static final String TYPE_CONSTRAINT = "TYPE_CONSTRAINT"; + public static final String TYPE_NAMESPACE = "TYPE_NAMESPACE"; + + private static final String ERR_UNKNOWN_ELEMENT_TYPE = "d_dictionary.model_diff.element_type.unknown"; + private static final String ERR_UNKNOWN_DIFF_TYPE = "d_dictionary.model_diff.diff_type.unknown"; + + private QName elementName; + private NamespaceDefinition namespace; + private String elementType; + private String diffType; + + public M2ModelDiff(QName elementName, String elementType, String diffType) + { + initModelDiff(elementName, elementType, diffType); + } + + public M2ModelDiff(QName elementName, NamespaceDefinition namespace, String elementType, String diffType) + { + initModelDiff(elementName, elementType, diffType); + this.namespace = namespace; + } + + private void initModelDiff(QName elementName, String elementType, String diffType) + { + // Check that all the passed values are not null + ParameterCheck.mandatory("elementName", elementName); + ParameterCheck.mandatoryString("elementType", elementType); + ParameterCheck.mandatoryString("diffType", diffType); + + if ((!elementType.equals(TYPE_TYPE)) && + (!elementType.equals(TYPE_ASPECT)) && + (!elementType.equals(TYPE_DEFAULT_ASPECT)) && + (!elementType.equals(TYPE_PROPERTY)) && + (!elementType.equals(TYPE_ASSOCIATION)) && + (!elementType.equals(TYPE_CONSTRAINT)) && + (!elementType.equals(TYPE_NAMESPACE)) + ) + { + throw new AlfrescoRuntimeException(ERR_UNKNOWN_ELEMENT_TYPE, new Object[] { elementType }); + } + + if ((! diffType.equals(DIFF_CREATED)) && + (! diffType.equals(DIFF_UPDATED)) && + (! diffType.equals(DIFF_UPDATED_INC)) && + (! diffType.equals(DIFF_DELETED)) && + (! diffType.equals(DIFF_UNCHANGED))) + { + throw new AlfrescoRuntimeException(ERR_UNKNOWN_DIFF_TYPE, new Object[] { diffType }); + } + + this.elementName = elementName; + this.elementType = elementType; + this.diffType = diffType; + } + + public QName getElementName() + { + return elementName; + } + + public String getElementType() + { + return elementType; + } + + public String getDiffType() + { + return diffType; + } + + public NamespaceDefinition getNamespaceDefinition() + { + return namespace; + } + + public String toString() + { + return new String(elementType + " " + elementName + " " + diffType); + } + } \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2NamedValue.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2NamedValue.java new file mode 100644 index 0000000000..fcd6e62567 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2NamedValue.java @@ -0,0 +1,98 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.List; + +/** + * Definition of a named value that can be used for property injection. + * + * @author Derek Hulley + */ +public class M2NamedValue +{ + private String name; + private String simpleValue = null; + private List listValue = null; + + /*package*/ M2NamedValue() + { + } + + + @Override + public String toString() + { + return (name + "=" + (simpleValue == null ? listValue : simpleValue)); + } + + public String getName() + { + return name; + } + + /** + * @return Returns the raw, unconverted value + */ + public String getSimpleValue() + { + return simpleValue; + } + + /** + * @return Returns the list of raw, unconverted values + */ + public List getListValue() + { + return listValue; + } + + public void setName(String name) + { + this.name = name; + } + + public void setSimpleValue(String simpleValue) + { + this.simpleValue = simpleValue; + } + + public void setListValue(List listValue) + { + this.listValue = listValue; + } + + public boolean hasSimpleValue() + { + return (this.simpleValue != null); + } + + public boolean hasListValue() + { + return (this.listValue != null); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2Namespace.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Namespace.java new file mode 100644 index 0000000000..ef1f7f537e --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Namespace.java @@ -0,0 +1,69 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + + +/** + * Namespace Definition. + * + * @author David Caruana + * + */ +public class M2Namespace +{ + private String uri = null; + private String prefix = null; + + + /*package*/ M2Namespace() + { + } + + + public String getUri() + { + return uri; + } + + + public void setUri(String uri) + { + this.uri = uri; + } + + + public String getPrefix() + { + return prefix; + } + + + public void setPrefix(String prefix) + { + this.prefix = prefix; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2NamespaceDefinition.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2NamespaceDefinition.java new file mode 100644 index 0000000000..245b6cab61 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2NamespaceDefinition.java @@ -0,0 +1,115 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.NamespaceDefinition; + + +/** + * Namespace Definition. + * + * + */ +public class M2NamespaceDefinition implements NamespaceDefinition +{ + ModelDefinition model = null; + private String uri = null; + private String prefix = null; + + + /*package*/ M2NamespaceDefinition(ModelDefinition model, String uri, String prefix) + { + this.model = model; + this.uri = uri; + this.prefix = prefix; + } + + public ModelDefinition getModel() + { + return model; + } + + public String getUri() + { + return uri; + } + + public String getPrefix() + { + return prefix; + } + + static List diffNamespaceDefinitionLists(Collection previousNamespaces, Collection newNamespaces) + { + List modelDiffs = new ArrayList(); + + for (NamespaceDefinition previousNamespace: previousNamespaces) + { + boolean found = false; + for (NamespaceDefinition newNamespace : newNamespaces) + { + if (newNamespace.getUri().equals(previousNamespace.getUri())) + { + if(!newNamespace.getPrefix().equals(previousNamespace.getPrefix())) + { + modelDiffs.add(new M2ModelDiff(newNamespace.getModel().getName(), newNamespace, M2ModelDiff.TYPE_NAMESPACE, M2ModelDiff.DIFF_UPDATED)); + } + found = true; + break; + } + } + + if (!found) + { + modelDiffs.add(new M2ModelDiff(previousNamespace.getModel().getName(), M2ModelDiff.TYPE_NAMESPACE, M2ModelDiff.DIFF_DELETED)); + } + } + + for (NamespaceDefinition newNamespace : newNamespaces) + { + boolean found = false; + for (NamespaceDefinition previousNamespace : previousNamespaces) + { + if (newNamespace.getUri().equals(previousNamespace.getUri())) + { + found = true; + break; + } + } + + if (!found) + { + modelDiffs.add(new M2ModelDiff(newNamespace.getModel().getName(), newNamespace, M2ModelDiff.TYPE_NAMESPACE, M2ModelDiff.DIFF_CREATED)); + } + } + return modelDiffs; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2Property.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Property.java new file mode 100644 index 0000000000..f00e49f3ad --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Property.java @@ -0,0 +1,334 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Properties; + + +/** + * Property Definition + * + * @author David Caruana + * + */ +public class M2Property +{ + private boolean isOverride = false; + private String name = null; + private String title = null; + private String description = null; + private String propertyType = null; + private boolean isProtected = false; + private boolean isMandatory = false; + private boolean isMandatoryEnforced = false; + private boolean isMultiValued = false; + private String defaultValue = null; + private Boolean isIndexed = Boolean.TRUE; + private Boolean isIndexedAtomically = null; + private Boolean isStoredInIndex = null; + private Boolean isFacetable = null; + private IndexTokenisationMode indexTokenisationMode = null; + private String analyserResourceBundleName; + private List constraints = new ArrayList(); + private Properties configProperties = new Properties(); + + /*package*/ M2Property() + { + } + + + /*package*/ M2Property(String name) + { + this.name = name; + } + + public boolean isOverride() + { + return isOverride; + } + + public void setOverride(boolean isOverride) + { + this.isOverride = isOverride; + } + + public String getName() + { + return name; + } + + + public void setName(String name) + { + this.name = name; + } + + + public String getTitle() + { + return title; + } + + + public void setTitle(String title) + { + this.title = title; + } + + + public String getDescription() + { + return description; + } + + + public void setDescription(String description) + { + this.description = description; + } + + + public String getType() + { + return propertyType; + } + + + public void setType(String type) + { + this.propertyType = type; + } + + + public boolean isProtected() + { + return isProtected; + } + + + public void setProtected(boolean isProtected) + { + this.isProtected = isProtected; + } + + + public boolean isMandatory() + { + return isMandatory; + } + + public void setMandatory(boolean isMandatory) + { + this.isMandatory = isMandatory; + } + + public boolean isMandatoryEnforced() + { + return isMandatoryEnforced; + } + + public void setMandatoryEnforced(boolean isMandatoryEnforced) + { + this.isMandatoryEnforced = isMandatoryEnforced; + } + + public boolean isMultiValued() + { + return isMultiValued; + } + + + public void setMultiValued(boolean isMultiValued) + { + this.isMultiValued = isMultiValued; + } + + + public String getDefaultValue() + { + if (defaultValue != null && M2Class.PROPERTY_PLACEHOLDER.matcher(defaultValue).matches()) + { + String key = defaultValue.substring(defaultValue.indexOf("${") + 2, defaultValue.indexOf("}")); + String value = defaultValue.substring(defaultValue.indexOf("|") + 1); + + return configProperties.getProperty(key, value); + } + else + { + return defaultValue; + } + } + + + public void setDefaultValue(String defaultValue) + { + this.defaultValue = defaultValue; + } + + + public Boolean isIndexed() + { + return isIndexed; + } + + + public void setIndexed(boolean isIndexed) + { + this.isIndexed = Boolean.valueOf(isIndexed); + } + + + public Boolean isStoredInIndex() + { + return isStoredInIndex; + } + + + public void setStoredInIndex(boolean isStoredInIndex) + { + this.isStoredInIndex = Boolean.valueOf(isStoredInIndex); + } + + public Boolean isFacetable() + { + return isFacetable; + } + + + public void setFacetable(boolean isFacetable) + { + this.isFacetable = Boolean.valueOf(isFacetable); + } + + + public Boolean isIndexedAtomically() + { + return isIndexedAtomically; + } + + + public void setIndexedAtomically(boolean isIndexedAtomically) + { + this.isIndexedAtomically = Boolean.valueOf(isIndexedAtomically); + } + + + public IndexTokenisationMode getIndexTokenisationMode() + { + return indexTokenisationMode; + } + + + public void setIndexTokenisationMode(IndexTokenisationMode indexTokenisationMode) + { + this.indexTokenisationMode = indexTokenisationMode; + } + + + public List getConstraints() + { + if (constraints == null) + { + return Collections.emptyList(); + } + else + { + return constraints; + } + } + + public boolean hasConstraints() + { + return ((this.constraints != null) && (constraints.size() > 0)); + } + + public M2Constraint addConstraintRef(String refName) + { + M2Constraint constraint = new M2Constraint(); + constraint.setRef(refName); + constraints.add(constraint); + return constraint; + } + + public M2Constraint addConstraint(String name, String type) + { + M2Constraint constraint = new M2Constraint(); + constraint.setName(name); + constraint.setType(type); + constraints.add(constraint); + return constraint; + } + + public void removeConstraintRef(String refName) + { + List cons = new ArrayList(getConstraints()); + for (M2Constraint con : cons) + { + if (con.getRef().equals(refName)) + { + constraints.remove(con); + } + } + } + + public void removeConstraint(String name) + { + if(name == null) + { + return; + } + List cons = new ArrayList(getConstraints()); + for (M2Constraint con : cons) + { + if (name.equals(con.getName())) + { + constraints.remove(con); + } + } + } + + /** + * @return String + */ + public String getAnalyserResourceBundleName() + { + return analyserResourceBundleName; + } + + + public void setAnalyserResourceBundleName(String analyserResourceBundleName) + { + this.analyserResourceBundleName = analyserResourceBundleName; + } + + public void setConfigProperties(Properties configProperties) + { + this.configProperties = configProperties; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2PropertyDefinition.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2PropertyDefinition.java new file mode 100644 index 0000000000..e69a2c765a --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2PropertyDefinition.java @@ -0,0 +1,783 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import static org.alfresco.service.cmr.dictionary.DictionaryException.DuplicateDefinitionException; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; + +import org.alfresco.repo.i18n.StaticMessageLookup; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.EqualsHelper; +import org.springframework.extensions.surf.util.I18NUtil; +import org.springframework.util.StringUtils; + + +/** + * Compiled Property Definition + * + * @author David Caruana + */ +/*package*/ class M2PropertyDefinition implements PropertyDefinition +{ + private ClassDefinition classDef; + private M2Property m2Property; + private QName name; + private QName propertyTypeName; + private DataTypeDefinition dataType; + private String analyserResourceBundleName; + private List constraintDefs = Collections.emptyList(); + private transient MessageLookup staticMessageLookup = new StaticMessageLookup(); + + /*package*/ M2PropertyDefinition( + ClassDefinition classDef, + M2Property m2Property, + NamespacePrefixResolver prefixResolver) + { + this.classDef = classDef; + this.m2Property = m2Property; + + // Resolve Names + this.name = QName.createQName(m2Property.getName(), prefixResolver); + this.propertyTypeName = QName.createQName(m2Property.getType(), prefixResolver); + this.analyserResourceBundleName = m2Property.getAnalyserResourceBundleName(); + } + + + /*package*/ M2PropertyDefinition( + ClassDefinition classDef, + PropertyDefinition propertyDef, + M2PropertyOverride override, + NamespacePrefixResolver prefixResolver, + Map modelConstraints) + { + this.classDef = classDef; + this.name = propertyDef.getName(); + this.dataType = propertyDef.getDataType(); + this.propertyTypeName = this.dataType.getName(); + this.m2Property = createOverriddenProperty(propertyDef, override, prefixResolver, modelConstraints); + } + + + /*package*/ void resolveDependencies( + ModelQuery query, + NamespacePrefixResolver prefixResolver, + Map modelConstraints) + { + if (propertyTypeName == null) + { + throw new DictionaryException( + "d_dictionary.property.err.property_type_not_specified", + name.toPrefixString()); + } + dataType = query.getDataType(propertyTypeName); + if (dataType == null) + { + throw new DictionaryException( + "d_dictionary.property.err.property_type_not_found", + propertyTypeName.toPrefixString(), name.toPrefixString()); + } + + // ensure content properties are not multi-valued + if (propertyTypeName.equals(DataTypeDefinition.CONTENT) && isMultiValued()) + { + throw new DictionaryException("d_dictionary.property.err.single_valued_content"); + } + + // Construct constraints + constraintDefs = buildConstraints( + m2Property.getConstraints(), + this, + prefixResolver, + modelConstraints); + } + + private static List buildConstraints( + List m2constraints, + M2PropertyDefinition m2PropertyDef, + NamespacePrefixResolver prefixResolver, + Map modelConstraints) + { + List constraints = new ArrayList(5); + Map constraintsByQName = new HashMap(7); + for (M2Constraint constraint : m2constraints) + { + // Consistent naming scheme for anonymous property constraints + if (constraint.getName() == null) + { + StringBuilder builder = new StringBuilder(); + builder.append(m2PropertyDef.classDef.getModel().getName().getLocalName()).append("_"); + builder.append(m2PropertyDef.classDef.getName().getLocalName()).append("_"); + builder.append(m2PropertyDef.getName().getLocalName()).append("_"); + builder.append("anon_"); + builder.append(constraints.size()); + QName newName = QName.createQName(m2PropertyDef.classDef.getModel().getName().getNamespaceURI(), builder.toString()); + constraint.setName(newName.getPrefixedQName(prefixResolver).toPrefixString()); + } + + ConstraintDefinition def = new M2ConstraintDefinition(m2PropertyDef, constraint, prefixResolver); + QName qname = def.getName(); + if (constraintsByQName.containsKey(qname)) + { + throw new DuplicateDefinitionException( + "d_dictionary.property.err.duplicate_constraint_on_property", + def.getName().toPrefixString(), m2PropertyDef.name.toPrefixString()); + } + else if (modelConstraints.containsKey(qname)) + { + throw new DuplicateDefinitionException( + "d_dictionary.model.err.duplicate_constraint_on_model", + def.getName().toPrefixString(), def.getModel().getName().toPrefixString()); + } + constraintsByQName.put(qname, def); + constraints.add(def); + modelConstraints.put(qname, def); + } + // done + return constraints; + } + + /** + * Create a property definition whose values are overridden + * + * @param propertyDef the property definition to override + * @param override the overridden values + * @return the property definition + */ + private M2Property createOverriddenProperty( + PropertyDefinition propertyDef, + M2PropertyOverride override, + NamespacePrefixResolver prefixResolver, + Map modelConstraints) + { + M2Property property = new M2Property(); + property.setOverride(true); + + // Process Default Value + String defaultValue = override.getDefaultValue(); + property.setDefaultValue(defaultValue == null ? propertyDef.getDefaultValue() : defaultValue); + + // Process Mandatory Value + Boolean isOverrideMandatory = override.isMandatory(); + Boolean isOverrideMandatoryEnforced = override.isMandatoryEnforced(); + if (isOverrideMandatory != null && propertyDef.isMandatory()) + { + // the override specified whether the property should be mandatory or not + // check that the mandatory enforcement is not relaxed + if (!isOverrideMandatory) + { + throw new DictionaryException( + "d_dictionary.property.err.cannot_relax_mandatory", + propertyDef.getName().toPrefixString()); + } + else if ((isOverrideMandatoryEnforced != null) && !isOverrideMandatoryEnforced && propertyDef.isMandatoryEnforced()) + { + throw new DictionaryException( + "d_dictionary.property.err.cannot_relax_mandatory_enforcement", + propertyDef.getName().toPrefixString()); + } + } + property.setMandatory(isOverrideMandatory == null ? propertyDef.isMandatory() : isOverrideMandatory); + property.setMandatoryEnforced(isOverrideMandatoryEnforced == null ? propertyDef.isMandatoryEnforced() : isOverrideMandatoryEnforced); + + // inherit or override constraints + List overrideConstraints = override.getConstraints(); + if (overrideConstraints != null) + { + constraintDefs = buildConstraints( + overrideConstraints, + this, + prefixResolver, + modelConstraints); + } + else + { + this.constraintDefs = propertyDef.getConstraints(); + } + + // Copy all other properties as they are + property.setDescription(propertyDef.getDescription(null)); + property.setIndexed(propertyDef.isIndexed()); + property.setIndexedAtomically(propertyDef.isIndexedAtomically()); + property.setMultiValued(propertyDef.isMultiValued()); + property.setProtected(propertyDef.isProtected()); + property.setStoredInIndex(propertyDef.isStoredInIndex()); + property.setTitle(propertyDef.getTitle(null)); + property.setIndexTokenisationMode(propertyDef.getIndexTokenisationMode()); + + return property; + } + + /** + * @see #getName() + */ + @Override + public String toString() + { + StringBuffer sb = new StringBuffer(); + sb.append("Name: " + getName() + "\n"); + sb.append("Title: " + getTitle(null) + "\n"); + sb.append("Description: " + getDescription(null) + "\n"); + sb.append("Default Value: " + getDefaultValue() + "\n"); + sb.append("DataType Name: " + getDataType().getName() + "\n"); + sb.append("ContainerClass Name: " + getContainerClass().getName() + "\n"); + sb.append("isMultiValued: " + isMultiValued() + "\n"); + sb.append("isMandatory: " + isMandatory() + "\n"); + sb.append("isMandatoryEnforced: " + isMandatoryEnforced() + "\n"); + sb.append("isProtected: " + isProtected() + "\n"); + sb.append("isIndexed: " + isIndexed() + "\n"); + sb.append("isStoredInIndex: " + isStoredInIndex() + "\n"); + sb.append("isIndexedAtomically: " + isIndexedAtomically() + "\n"); + sb.append("indexTokenisationMode: " + getIndexTokenisationMode() + "\n"); + + return sb.toString(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.PropertyDefinition#getModel() + */ + public ModelDefinition getModel() + { + return classDef.getModel(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.PropertyDefinition#getName() + */ + public QName getName() + { + return name; + } + + public String getTitle() + { + return getTitle(staticMessageLookup); + } + + public String getTitle(MessageLookup messageLookup) + { + String value = M2Label.getLabel(classDef.getModel(), messageLookup, "property", name, "title"); + if (value == null) + { + value = m2Property.getTitle(); + } + return value; + } + + public String getTitle(MessageLookup messageLookup, Locale locale) + { + String value = M2Label.getLabel(locale, classDef.getModel(), messageLookup, "property", name, "title"); + if (value == null) + { + value = m2Property.getTitle(); + } + return value; + } + + public String getDescription() + { + return getDescription(staticMessageLookup); + } + + public String getDescription(MessageLookup messageLookup) + { + String value = M2Label.getLabel(classDef.getModel(), messageLookup, "property", name, "description"); + if (value == null) + { + value = m2Property.getDescription(); + } + return value; + } + + public String getDescription(MessageLookup messageLookup, Locale locale) + { + String value = M2Label.getLabel(locale, classDef.getModel(), messageLookup, "property", name, "description"); + if (value == null) + { + value = m2Property.getDescription(); + } + return value; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.PropertyDefinition#getDefaultValue() + */ + public String getDefaultValue() + { + return m2Property.getDefaultValue(); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.PropertyDefinition#getPropertyType() + */ + public DataTypeDefinition getDataType() + { + return dataType; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.PropertyDefinition#getContainerClass() + */ + public ClassDefinition getContainerClass() + { + return classDef; + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.PropertyDefinition#isOverride() + */ + public boolean isOverride() + { + return m2Property.isOverride(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.PropertyDefinition#isMultiValued() + */ + public boolean isMultiValued() + { + return m2Property.isMultiValued(); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.PropertyDefinition#isMandatory() + */ + public boolean isMandatory() + { + return m2Property.isMandatory(); + } + + public boolean isMandatoryEnforced() + { + return m2Property.isMandatoryEnforced(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.PropertyDefinition#isProtected() + */ + public boolean isProtected() + { + return m2Property.isProtected(); + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.PropertyDefinition#isIndexed() + */ + public boolean isIndexed() + { + if(m2Property.isIndexed() == null) + { + return true; + } + else + { + return m2Property.isIndexed(); + } + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.PropertyDefinition#isStoredInIndex() + */ + public boolean isStoredInIndex() + { + if(m2Property.isStoredInIndex() == null) + { + return false; + } + else + { + return m2Property.isStoredInIndex(); + } + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.PropertyDefinition#isIndexedAtomically() + */ + public boolean isIndexedAtomically() + { + if(m2Property.isIndexedAtomically() == null) + { + return true; + } + else + { + return m2Property.isIndexedAtomically(); + } + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.dictionary.PropertyDefinition#isTokenisedInIndex() + */ + public IndexTokenisationMode getIndexTokenisationMode() + { + if(m2Property.getIndexTokenisationMode() == null) + { + return IndexTokenisationMode.TRUE; + } + else + { + return m2Property.getIndexTokenisationMode(); + } + } + + public Facetable getFacetable() + { + if(m2Property.isFacetable() == null) + { + return Facetable.UNSET; + } + else + { + if(m2Property.isFacetable().booleanValue()) + { + return Facetable.TRUE; + } + else + { + return Facetable.FALSE; + } + } + } + + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.PropertyDefinition#getConstraints() + */ + public List getConstraints() + { + return constraintDefs; + } + + /* package */ M2ModelDiff diffProperty(PropertyDefinition propDef) + { + M2ModelDiff modelDiff = null; + boolean isUpdated = false; + boolean isUpdatedIncrementally = false; + + if (this == propDef) + { + modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UNCHANGED); + return modelDiff; + } + + // check name - cannot be null + if (! name.equals(propDef.getName())) + { + isUpdated = true; + } + + // check title + if (! EqualsHelper.nullSafeEquals(getTitle(null), propDef.getTitle(null), false)) + { + isUpdatedIncrementally = true; + } + + // check description + if (! EqualsHelper.nullSafeEquals(getDescription(null), propDef.getDescription(null), false)) + { + isUpdatedIncrementally = true; + } + + // check default value + if (! EqualsHelper.nullSafeEquals(getDefaultValue(), propDef.getDefaultValue(), false)) + { + isUpdatedIncrementally = true; + } + + // check datatype qname (TODO check datatype defs separately) + if (! EqualsHelper.nullSafeEquals(getDataType().getName(), propDef.getDataType().getName())) + { + isUpdated = true; + } + + // check container class qname + if (! EqualsHelper.nullSafeEquals(getContainerClass().getName(), propDef.getContainerClass().getName())) + { + isUpdated = true; + } + + // check multi-valued + if (isMultiValued() != propDef.isMultiValued()) + { + isUpdated = true; + } + + // check mandatory + if (isMandatory() != propDef.isMandatory()) + { + isUpdated = true; + } + + // check mandatory enforced + if (isMandatoryEnforced() != propDef.isMandatoryEnforced()) + { + isUpdated = true; + } + + // check protected + if (isProtected() != propDef.isProtected()) + { + isUpdated = true; + } + + // + // property indexing - is index enabled -> stored, atomic, tokenized (true, false, both) + // + // + // true + // false + // both + // + // + + if (isIndexed() != propDef.isIndexed()) + { + isUpdated = true; + } + + if (isStoredInIndex() != propDef.isStoredInIndex()) + { + isUpdatedIncrementally = true; + } + + if (isIndexedAtomically() != propDef.isIndexedAtomically()) + { + isUpdatedIncrementally = true; + } + + if (! EqualsHelper.nullSafeEquals(getIndexTokenisationMode().toString(), propDef.getIndexTokenisationMode().toString(), false)) + { + isUpdated = true; + } + + + // check override + if (isOverride() != propDef.isOverride()) + { + isUpdated = true; + } + + // TODO - check prop constraints (inline and referenced) + + if (isUpdated) + { + modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UPDATED); + } + else if (isUpdatedIncrementally) + { + modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UPDATED_INC); + } + else + { + modelDiff = new M2ModelDiff(name, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UNCHANGED); + } + + return modelDiff; + } + + /*package*/ static Collection diffPropertyLists(Collection previousProperties, Collection newProperties) + { + List modelDiffs = new ArrayList(); + + for (PropertyDefinition previousProperty : previousProperties) + { + boolean found = false; + for (PropertyDefinition newProperty : newProperties) + { + if (newProperty.getName().equals(previousProperty.getName())) + { + modelDiffs.add(((M2PropertyDefinition)previousProperty).diffProperty(newProperty)); + found = true; + break; + } + } + + if (! found) + { + modelDiffs.add(new M2ModelDiff(previousProperty.getName(), M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_DELETED)); + } + } + + for (PropertyDefinition newProperty : newProperties) + { + boolean found = false; + for (PropertyDefinition previousProperty : previousProperties) + { + if (newProperty.getName().equals(previousProperty.getName())) + { + found = true; + break; + } + } + + if (! found) + { + modelDiffs.add(new M2ModelDiff(newProperty.getName(), M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_CREATED)); + } + } + + return modelDiffs; + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.PropertyDefinition#getAnalyserResourceBundleName() + */ + @Override + public String getAnalyserResourceBundleName() + { + return analyserResourceBundleName; + } + + @Override + public String resolveAnalyserClassName() + { + return resolveAnalyserClassName(I18NUtil.getLocale()); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.dictionary.PropertyDefinition#getAnalyserClassName(java.lang.String, java.util.Locale) + */ + @Override + public String resolveAnalyserClassName(Locale locale +) + { + ClassLoader resourceBundleClassLoader = getModel().getDictionaryDAO().getResourceClassLoader(); + if(resourceBundleClassLoader == null) + { + resourceBundleClassLoader = this.getClass().getClassLoader(); + } + + StringBuilder keyBuilder = new StringBuilder(64); + keyBuilder.append(getDataType().getModel().getName().toPrefixString()); + keyBuilder.append(".datatype"); + keyBuilder.append(".").append(getDataType().getName().toPrefixString()); + keyBuilder.append(".analyzer"); + String key = StringUtils.replace(keyBuilder.toString(), ":", "_"); + + String analyserClassName = null; + + String analyserResourceBundleName = getAnalyserResourceBundleName(); + if(analyserResourceBundleName != null) + { + ResourceBundle bundle = ResourceBundle.getBundle(analyserResourceBundleName, locale, resourceBundleClassLoader); + if(bundle.containsKey(key)) + { + analyserClassName = bundle.getString(key); + } + } + + // walk containing class and its hierarchy + + ClassDefinition classDefinition = null; + ClassDefinition parentClassDefinition = null; + while(analyserClassName == null) + { + if(classDefinition == null) + { + classDefinition = getContainerClass(); + } + else + { + if(parentClassDefinition == null) + { + break; + } + else + { + classDefinition = parentClassDefinition; + } + } + + parentClassDefinition = classDefinition.getParentClassDefinition(); + + analyserResourceBundleName = classDefinition.getAnalyserResourceBundleName(); + if(analyserResourceBundleName != null) + { + ResourceBundle bundle = ResourceBundle.getBundle(analyserResourceBundleName, locale, resourceBundleClassLoader); + if(bundle.containsKey(key)) + { + analyserClassName = bundle.getString(key); + } + } + if(analyserClassName == null) + { + if((parentClassDefinition == null) || !classDefinition.getModel().getName().equals(parentClassDefinition.getModel().getName())) + { + analyserResourceBundleName = classDefinition.getModel().getAnalyserResourceBundleName(); + if(analyserResourceBundleName != null) + { + ResourceBundle bundle = ResourceBundle.getBundle(analyserResourceBundleName, locale, resourceBundleClassLoader); + if(bundle.containsKey(key)) + { + analyserClassName = bundle.getString(key); + } + } + } + } + } + String defaultAnalyserResourceBundleName = this.getContainerClass().getModel().getDictionaryDAO().getDefaultAnalyserResourceBundleName(); + if(analyserClassName == null) + { + if(defaultAnalyserResourceBundleName != null) + { + ResourceBundle bundle = ResourceBundle.getBundle(defaultAnalyserResourceBundleName, locale, resourceBundleClassLoader); + if(bundle.containsKey(key)) + { + analyserClassName = bundle.getString(key); + } + } + } + if(analyserClassName == null) + { + analyserClassName = getDataType().resolveAnalyserClassName(locale); + } + return analyserClassName; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2PropertyOverride.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2PropertyOverride.java new file mode 100644 index 0000000000..b8703961c1 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2PropertyOverride.java @@ -0,0 +1,110 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.List; +import java.util.Properties; + + +/** + * Property override definition + * + * @author David Caruana + * + */ +public class M2PropertyOverride +{ + private String name; + private Boolean isMandatory; + private Boolean isMandatoryEnforced; + private String defaultValue; + private List constraints; + private Properties configProperties = new Properties(); + + /*package*/ M2PropertyOverride() + { + } + + + public String getName() + { + return name; + } + + + public void setName(String name) + { + this.name = name; + } + + + public Boolean isMandatory() + { + return isMandatory; + } + + + public void setMandatory(Boolean isMandatory) + { + this.isMandatory = isMandatory; + } + + public Boolean isMandatoryEnforced() + { + return isMandatoryEnforced; + } + + public String getDefaultValue() + { + if (defaultValue != null && M2Class.PROPERTY_PLACEHOLDER.matcher(defaultValue).matches()) + { + String key = defaultValue.substring(defaultValue.indexOf("${") + 2, defaultValue.indexOf("}")); + String value = defaultValue.substring(defaultValue.indexOf("|") + 1); + + return configProperties.getProperty(key, value); + } + else + { + return defaultValue; + } + } + + + public void setDefaultValue(String defaultValue) + { + this.defaultValue = defaultValue; + } + + public List getConstraints() + { + return constraints; + } + + public void setConfigProperties(Properties configProperties) + { + this.configProperties = configProperties; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2Type.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Type.java new file mode 100644 index 0000000000..50df31f6b7 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2Type.java @@ -0,0 +1,41 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + + +/** + * Type Definition + * + * @author David Caruana + * + */ +public class M2Type extends M2Class +{ + /*package*/ M2Type() + { + super(); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2TypeDefinition.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2TypeDefinition.java new file mode 100644 index 0000000000..88b64e1990 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2TypeDefinition.java @@ -0,0 +1,79 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.Map; + +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; + + +/** + * Compiled Type Definition + * + * @author David Caruana + */ +/*package*/ class M2TypeDefinition extends M2ClassDefinition + implements TypeDefinition +{ + /*package*/ M2TypeDefinition(ModelDefinition model, M2Type m2Type, NamespacePrefixResolver resolver, Map modelProperties, Map modelAssociations) + { + super(model, m2Type, resolver, modelProperties, modelAssociations); + } + + @Override + public String getDescription(MessageLookup messageLookup) + { + String value = M2Label.getLabel(model, messageLookup, "type", name, "description"); + + // if we don't have a description call the super class + if (value == null) + { + value = super.getDescription(messageLookup); + } + + return value; + } + + @Override + public String getTitle(MessageLookup messageLookup) + { + String value = M2Label.getLabel(model, messageLookup, "type", name, "title"); + + // if we don't have a title call the super class + if (value == null) + { + value = super.getTitle(messageLookup); + } + + return value; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/M2XML.java b/data-model/src/main/java/org/alfresco/repo/dictionary/M2XML.java new file mode 100644 index 0000000000..813d06c11c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/M2XML.java @@ -0,0 +1,102 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.swing.text.StyledEditorKit.BoldAction; + +import org.alfresco.util.CachingDateFormat; + + +/** + * Support translating model from and to XML + * + * @author David Caruana + * + */ +public class M2XML +{ + + /** + * Convert XML date (of the form yyyy-MM-dd) to Date + * + * @param date the xml representation of the date + * @return the date + * @throws ParseException + */ + public static Date deserialiseDate(String date) + throws ParseException + { + Date xmlDate = null; + if (date != null) + { + SimpleDateFormat df = CachingDateFormat.getDateOnlyFormat(); + xmlDate = df.parse(date); + } + return xmlDate; + } + + + /** + * Convert date to XML date (of the form yyyy-MM-dd) + * + * @param date the date + * @return the xml representation of the date + */ + public static String serialiseDate(Date date) + { + String xmlDate = null; + if (date != null) + { + SimpleDateFormat df = CachingDateFormat.getDateOnlyFormat(); + xmlDate = df.format(date); + } + return xmlDate; + } + + public static Boolean deserialiseBoolean(String booleanString) throws ParseException + { + Boolean bool = null; + if((booleanString != null) && booleanString.length() > 0) + { + bool = Boolean.valueOf(booleanString); + } + return bool; + } + + public static String serialiseBoolean(Boolean bool) + { + String booleanString = null; + if (bool != null) + { + booleanString = bool.toString(); + } + return booleanString; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/ModelQuery.java b/data-model/src/main/java/org/alfresco/repo/dictionary/ModelQuery.java new file mode 100644 index 0000000000..d685e4a09c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/ModelQuery.java @@ -0,0 +1,110 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.QName; + + +/** + * Access to model items. + * + * @author David Caruana + * + */ +/*package*/ interface ModelQuery +{ + /** + * Gets the specified data type + * + * @param name name of the data type + * @return data type definition + */ + public DataTypeDefinition getDataType(QName name); + + /** + * Gets the data type for the specified Java Class + * + * @param javaClass the java class + * @return the data type definition (or null, if mapping is not available) + */ + public DataTypeDefinition getDataType(Class javaClass); + + /** + * Gets the specified type + * + * @param name name of the type + * @return type definition + */ + public TypeDefinition getType(QName name); + + /** + * Gets the specified aspect + * + * @param name name of the aspect + * @return aspect definition + */ + public AspectDefinition getAspect(QName name); + + /** + * Gets the specified class + * + * @param name name of the class + * @return class definition + */ + public ClassDefinition getClass(QName name); + + /** + * Gets the specified property + * + * @param name name of the property + * @return property definition + */ + public PropertyDefinition getProperty(QName name); + + /** + * Gets the specified property constraint + * + * @param name the qualified name of the property constraint + * @return ConstraintDefinition + */ + public ConstraintDefinition getConstraint(QName name); + + /** + * Gets the specified association + * + * @param name name of the association + * @return association definition + */ + public AssociationDefinition getAssociation(QName name); + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/NamespaceDAO.java b/data-model/src/main/java/org/alfresco/repo/dictionary/NamespaceDAO.java new file mode 100644 index 0000000000..9a9d805508 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/NamespaceDAO.java @@ -0,0 +1,90 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import org.alfresco.service.namespace.NamespacePrefixResolver; + + +/** + * Namespace DAO Interface. + * + * This DAO is responsible for retrieving and creating Namespace definitions. + * + * @author David Caruana + */ +public interface NamespaceDAO extends NamespacePrefixResolver +{ + /** + * Add a namespace URI + * + * @param uri the namespace uri to add + */ + public void addURI(String uri); + + /** + * Remove the specified URI + * + * @param uri the uri to remove + */ + public void removeURI(String uri); + + /** + * Add a namespace prefix + * + * @param prefix the prefix + * @param uri the uri to prefix + */ + public void addPrefix(String prefix, String uri); + + /** + * Remove a namspace prefix + * + * @param prefix the prefix to remove + */ + public void removePrefix(String prefix); + + /** + * Initialise Namespaces + */ +// public void init(); + +// public void afterDictionaryInit(); + + /** + * Destroy Namespaces + */ +// public void destroy(); + + /** + * Register with the Dictionary + */ +// public void registerDictionary(DictionaryDAO dictionaryDAO); + + /** + * Clear NamespaceLocal + */ +// public void clearNamespaceLocal(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/TenantDictionaryRegistryImpl.java b/data-model/src/main/java/org/alfresco/repo/dictionary/TenantDictionaryRegistryImpl.java new file mode 100644 index 0000000000..ab671a89f8 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/TenantDictionaryRegistryImpl.java @@ -0,0 +1,253 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.NamespaceException; +import org.alfresco.service.namespace.QName; + +/** + * Tenant-specific dictionary registry. + * + * @author sglover + * + */ +public class TenantDictionaryRegistryImpl extends AbstractDictionaryRegistry +{ + private String tenantDomain; + + public TenantDictionaryRegistryImpl(DictionaryDAO dictionaryDAO, String tenantDomain) + { + super(dictionaryDAO); + this.tenantDomain = tenantDomain; + } + + public String getTenantDomain() + { + return tenantDomain; + } + + private DictionaryRegistry getParent() + { + return dictionaryDAO.getDictionaryRegistry(""); + } + + @Override + public QName putModelImpl(CompiledModel model) + { + if(getParent().modelExists(model.getModelDefinition().getName())) + { + throw new IllegalArgumentException("Cannot change core model: " + model); + } + QName ret = super.putModelImpl(model); + + return ret; + } + + @Override + public Map getCompiledModels(boolean includeInherited) + { + Map ret = new HashMap(); + ret.putAll(super.getCompiledModels(includeInherited)); + if(includeInherited) + { + ret.putAll(getParent().getCompiledModels(includeInherited)); + } + return ret; + } + + @Override + public List getModelsForUri(String uri) + { + List models = new LinkedList<>(); + List parentModels = getParent().getModelsForUri(uri); + models.addAll(parentModels); + models.addAll(getModelsForUriImpl(uri)); + return models; + } + + @Override + public CompiledModel getModel(QName name) + { + CompiledModel model = getModelImpl(name); + if(model == null) + { + // try parent + model = getParent().getModel(name); + } + return model; + } + + @Override + public void removeModel(QName modelName) + { + CompiledModel model = removeModelImpl(modelName); + if(model == null) + { + // try parent + getParent().removeModel(modelName); + } + } + + @Override + public AspectDefinition getAspect(QName aspectName) + { + AspectDefinition aspect = getAspectImpl(aspectName); + if(aspect == null) + { + // try parent + aspect = getParent().getAspect(aspectName); + } + + return aspect; + } + + @Override + public boolean isModelInherited(QName modelName) + { + return (getParent().getModel(modelName) != null); + } + + @Override + public Map getPrefixesCache() + { + Map prefixesCache = new HashMap(); + + Map parentPrefixes = getParent().getPrefixesCache(); + prefixesCache.putAll(parentPrefixes); + prefixesCache.putAll(getPrefixesCacheImpl()); + + return prefixesCache; + } + + @Override + public List getUrisCache() + { + List urisCache = new LinkedList(); + + List parentUris = getParent().getUrisCache(); + urisCache.addAll(parentUris); + urisCache.addAll(getUrisCacheImpl()); + + return urisCache; + } + + @Override + public Collection getPrefixes(String URI) + { + Collection prefixes = getParent().getPrefixes(URI); + prefixes.addAll(getPrefixesImpl(URI)); + return prefixes; + } + + @Override + public void addURI(String uri) + { + if(getParent().hasURI(uri)) + { + throw new NamespaceException("URI " + uri + " has already been defined"); + } + addURIImpl(uri); + } + + @Override + public void addPrefix(String prefix, String uri) + { + if(getParent().hasPrefix(prefix)) + { + throw new NamespaceException("Prefix " + prefix + " has already been defined"); + } + addPrefixImpl(prefix, uri); + } + + @Override + public void removeURI(String uri) + { + if(!removeURIImpl(uri)) + { + // try parent + getParent().removeURI(uri); + } + } + + @Override + public void removePrefix(String prefix) + { + if(!removePrefixImpl(prefix)) + { + // try parent + getParent().removePrefix(prefix); + } + } + + @Override + protected void initImpl() + { + long startTime = System.currentTimeMillis(); + + // populate the dictionary based on registered sources (only for core registry) + for (DictionaryListener dictionaryDeployer : dictionaryDAO.getDictionaryListeners()) + { + dictionaryDeployer.onDictionaryInit(); + } + + // Done + if (logger.isInfoEnabled()) + { + Map models = getCompiledModels(false); + logger.info("Init Tenant Dictionary: model count = "+(models != null ? models.size() : 0) + +" in "+(System.currentTimeMillis()-startTime)+" msecs ["+Thread.currentThread()+"]"); + } + } + + @Override + public TypeDefinition getType(QName typeName) + { + TypeDefinition type = getTypeImpl(typeName); + if(type == null) + { + // try parent + type = getParent().getType(typeName); + } + return type; + } + + @Override + public void removeImpl() + { + for(DictionaryListener listener : dictionaryDAO.getDictionaryListeners()) + { + listener.afterDictionaryDestroy(); + } + } +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/AbstractConstraint.java b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/AbstractConstraint.java new file mode 100644 index 0000000000..ca308231a5 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/AbstractConstraint.java @@ -0,0 +1,210 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary.constraint; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.service.cmr.dictionary.Constraint; +import org.alfresco.service.cmr.dictionary.ConstraintException; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; + +/** + * Base services for constraints. + * + * @author Derek Hulley + */ +public abstract class AbstractConstraint implements Constraint +{ + public static final String ERR_PROP_NOT_SET = "d_dictionary.constraint.err.property_not_set"; + public static final String ERR_EVALUATE_EXCEPTION = "d_dictionary.constraint.err.evaluate_exception"; + + + /** The constraint name. May be useful in error messages */ + private String shortName; + private String title; + + private ConstraintRegistry registry; + + /** + * Sets the constraint name. Automatically called after construction. Please excuse the strange method name as we + * want the property name to begin with an underscore to avoid property name clashes. + * + * @param shortName String + * @deprecated + */ + public void set_shortName(String shortName) + { + setShortName(shortName); + } + + /** + * Sets the constraint name + * @param name String + */ + public void setShortName(String name) + { + this.shortName = name; + } + + /** + * Gets the constraint name. + * + * @return the constraint name. + */ + public String getShortName() + { + return this.shortName; + } + + /** + * Optionally specify the registry that will be used to register the constraint. + * This is used when instantiating constraints outside the dictionary. + * + * @param registry the constraint registry + */ + public void setRegistry(ConstraintRegistry registry) + { + this.registry = registry; + } + + public String getType() + { + return this.getClass().getName(); + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getTitle() + { + return title; + } + + public Map getParameters() + { + return new HashMap(3); + } + + /** + * {@inheritDoc} + *

+ * Registers the constraint with the registry, if present. Call this method if + * you want the constraint to be auto-registered. + */ + public void initialize() + { + if (registry != null) + { + registry.register(shortName, this); + } + } + + /** + * Check that the given value is not null. + * + * @param name the name of the property + * @param value the value to check for null + * + * @throws DictionaryException if the the property is null + */ + protected void checkPropertyNotNull(String name, Object value) + { + if (value == null) + { + throw new DictionaryException(AbstractConstraint.ERR_PROP_NOT_SET, name, getShortName()); + } + } + + /** + * @see #evaluateSingleValue(Object) + * @see #evaluateCollection(Collection) + */ + @SuppressWarnings("unchecked") + public final void evaluate(Object value) + { + if (value == null) + { + // null values are never evaluated + return; + } + try + { + // ensure that we can handle collections + if (DefaultTypeConverter.INSTANCE.isMultiValued(value)) + { + Collection collection = DefaultTypeConverter.INSTANCE.getCollection(Object.class, value); + evaluateCollection(collection); + } + else + { + evaluateSingleValue(value); + } + } + catch (ConstraintException e) + { + // this can go + throw e; + } + catch (Throwable e) + { + throw new DictionaryException(AbstractConstraint.ERR_EVALUATE_EXCEPTION, this, e.getMessage()); + } + } + + /** + * Only override if there is some specific evaluation that needs to be performed on the + * collection as a whole. + * + * @param collection the collection of values to evaluate + * + * @see #evaluateSingleValue(Object) + */ + protected void evaluateCollection(Collection collection) + { + for (Object value : collection) + { + if (value == null) + { + // contract states that it will always pass + continue; + } + evaluateSingleValue(value); + } + } + + /** + * Support for evaluation of properties. The value passed in will never be a + * Collection and will never be null. + * + * @throws ConstraintException throw this when the evaluation fails + */ + protected abstract void evaluateSingleValue(Object value); +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/ConstraintRegistry.java b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/ConstraintRegistry.java new file mode 100644 index 0000000000..946a0a0943 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/ConstraintRegistry.java @@ -0,0 +1,94 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary.constraint; + +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.service.cmr.dictionary.Constraint; + +/** + * A registry of constraints. + * + * @author Derek Hulley + * @since 3.2 + */ +public class ConstraintRegistry +{ + private static ConstraintRegistry instance = new ConstraintRegistry(); + + private Map constraints; + + /** + * @return Returns the singleton + */ + public static ConstraintRegistry getInstance() + { + return instance; + } + + /** + * Private constructor + * @see #getInstance() + */ + private ConstraintRegistry() + { + constraints = new HashMap(13); + } + + /** + * Register the constraint by name + */ + public void register(String name, Constraint constraint) + { + if (this == instance) + { + constraints.put(name, constraint); + } + else + { + instance.register(name, constraint); + } + } + + /** + * Get the constraint by name + * + * @param name the name by which the constraint was registered + * @return Returns the constraint or null if it does not exist. + */ + public Constraint getConstraint(String name) + { + if (this == instance) + { + return constraints.get(name); + } + else + { + return instance.getConstraint(name); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/ListOfValuesConstraint.java b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/ListOfValuesConstraint.java new file mode 100644 index 0000000000..72565ec044 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/ListOfValuesConstraint.java @@ -0,0 +1,301 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary.constraint; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.service.cmr.dictionary.ConstraintException; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.service.cmr.repository.datatype.TypeConversionException; +import org.springframework.extensions.surf.util.I18NUtil; +import org.springframework.util.StringUtils; + +/** + * Constraint implementation that ensures the value is one of a constrained + * list of values. By default, this constraint is case-sensitive. + * + * @see #setAllowedValues(List) + * @see #setCaseSensitive(boolean) + * + * @author Derek Hulley + */ +public class ListOfValuesConstraint extends AbstractConstraint +{ + private static final String LOV_CONSTRAINT_VALUE = "listconstraint"; + public static final String CONSTRAINT_TYPE = "LIST"; + + public static final String CASE_SENSITIVE_PARAM = "caseSensitive"; + public static final String ALLOWED_VALUES_PARAM = "allowedValues"; + public static final String SORTED_PARAM = "sorted"; + + private static final String ERR_NO_VALUES = "d_dictionary.constraint.list_of_values.no_values"; + private static final String ERR_NON_STRING = "d_dictionary.constraint.string_length.non_string"; + private static final String ERR_INVALID_VALUE = "d_dictionary.constraint.list_of_values.invalid_value"; + + private List allowedValues; + private List allowedValuesUpper; + private Set allowedValuesSet; + private Set allowedValuesUpperSet; + protected boolean caseSensitive; + protected boolean sorted; + + public ListOfValuesConstraint() + { + caseSensitive = true; + sorted = false; + allowedValues = Collections.emptyList(); + allowedValuesUpper = Collections.emptyList(); + allowedValuesSet = Collections.emptySet(); + allowedValuesUpperSet = Collections.emptySet(); + } + + /** + * {@inheritDoc} + */ + @Override + public String getType() + { + return CONSTRAINT_TYPE; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(80); + sb.append("ListOfValuesConstraint") + .append("[ allowedValues=").append(allowedValues) + .append(", caseSensitive=").append(caseSensitive) + .append(", sorted=").append(sorted) + .append("]"); + return sb.toString(); + } + + /** + * Get the allowed values. Note that these are String instances, but may + * represent non-String values. It is up to the caller to distinguish. + * + * Sorts list if appropriate. + * + * @return Returns the values allowed + */ + public List getAllowedValues() + { + List rawValues = getRawAllowedValues(); + if (sorted == true) + { + List values = new ArrayList(rawValues); + Collections.sort(values); + return values; + } + else + { + return rawValues; + } + } + + /** + * Get the allowed values. Note that these are String instances, but may + * represent non-String values. It is up to the caller to distinguish. + * + * @return Returns the values allowed + */ + protected List getRawAllowedValues() + { + return allowedValues; + } + + /** + * Get the display label for the specified allowable value in this constraint. + * A key is constructed as follows: + *
+     *   "listconstraint." + constraintName + "." + constraintAllowableValue.
+     *   e.g. listconstraint.test_listConstraintOne.VALUE_ONE.
+     * 
+ * This key is then used to look up a properties bundle for the localised display label. + * Spaces are allowed in the keys, but they should be escaped in the properties file as follows: + *
+     * listconstraint.test_listConstraintOne.VALUE\ WITH\ SPACES=Display label
+     * 
+ * + * @param constraintAllowableValue String + * @param messageLookup MessageLookup + * @return the localised display label for the specified constraint value in the current locale. + * If no localisation is defined, it will return the allowed value itself. + * If the specified allowable value is not in the model, returns null. + * @since 4.0 + * @see I18NUtil#getLocale() + */ + public String getDisplayLabel(String constraintAllowableValue, MessageLookup messageLookup) + { + if (!allowedValues.contains(constraintAllowableValue)) + { + return null; + } + + String key = LOV_CONSTRAINT_VALUE; + key += "." + this.getShortName(); + key += "." + constraintAllowableValue; + key = StringUtils.replace(key, ":", "_"); + + String message = messageLookup.getMessage(key, I18NUtil.getLocale()); + return message == null ? constraintAllowableValue : message; + } + + + /** + * Set the values that are allowed by the constraint. + * + * @param allowedValues a list of allowed values + */ + public void setAllowedValues(List allowedValues) + { + if (allowedValues == null) + { + throw new DictionaryException(ERR_NO_VALUES); + } + int valueCount = allowedValues.size(); + if (valueCount == 0) + { + throw new DictionaryException(ERR_NO_VALUES); + } + this.allowedValues = Collections.unmodifiableList(allowedValues); + this.allowedValuesSet = new HashSet(allowedValues); + // make the upper case versions + this.allowedValuesUpper = new ArrayList(valueCount); + this.allowedValuesUpperSet = new HashSet(valueCount); + for (String allowedValue : this.allowedValues) + { + String allowedValueUpper = allowedValue.toUpperCase(); + allowedValuesUpper.add(allowedValueUpper); + allowedValuesUpperSet.add(allowedValueUpper); + } + } + + /** + * @return Returns true if this constraint is case-sensitive (default) + */ + public boolean isCaseSensitive() + { + return caseSensitive; + } + + /** + * Set the handling of case checking. + * + * @param caseSensitive true if the constraint is case-sensitive (default), + * or false for case-insensitive. + */ + public void setCaseSensitive(boolean caseSensitive) + { + this.caseSensitive = caseSensitive; + } + + /** + * Indicates whether the list of values are sorted or not. + * + * @return true if sorted, false otherwise + */ + public boolean isSorted() + { + return sorted; + } + + /** + * Set whether the values are ordered or not. + * + * @param sorted true if sorted, false otherwise + */ + public void setSorted(boolean sorted) + { + this.sorted = sorted; + } + + /** + * @see org.alfresco.repo.dictionary.constraint.AbstractConstraint#initialize() + */ + @Override + public void initialize() + { + super.initialize(); + checkPropertyNotNull(ALLOWED_VALUES_PARAM, allowedValues); + } + + /** + * @see org.alfresco.repo.dictionary.constraint.AbstractConstraint#getParameters() + */ + @Override + public Map getParameters() + { + Map params = new HashMap(2); + + params.put(CASE_SENSITIVE_PARAM, this.caseSensitive); + params.put(ALLOWED_VALUES_PARAM, this.allowedValues); + params.put(SORTED_PARAM, this.sorted); + + return params; + } + + /** + * @see org.alfresco.repo.dictionary.constraint.AbstractConstraint#evaluateSingleValue(java.lang.Object) + */ + @Override + protected void evaluateSingleValue(Object value) + { + // convert the value to a String + String valueStr = null; + try + { + valueStr = DefaultTypeConverter.INSTANCE.convert(String.class, value); + } + catch (TypeConversionException e) + { + throw new ConstraintException(ERR_NON_STRING, value); + } + // check that the value is in the set of allowed values + if (caseSensitive) + { + if (!allowedValuesSet.contains(valueStr)) + { + throw new ConstraintException(ERR_INVALID_VALUE, value); + } + } + else + { + if (!allowedValuesUpperSet.contains(valueStr.toUpperCase())) + { + throw new ConstraintException(ERR_INVALID_VALUE, value); + } + } + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/NameChecker.java b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/NameChecker.java new file mode 100644 index 0000000000..d8cd8a84f5 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/NameChecker.java @@ -0,0 +1,102 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary.constraint; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.service.cmr.dictionary.Constraint; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.PropertyCheck; +import org.springframework.beans.factory.InitializingBean; + +/** + * Loads cm:filename constraint from dictionary to use it during batch jobs + * + * @see MNT-9414 + * + * @author Viachaslau Tsikhanovich * + */ +public class NameChecker implements InitializingBean +{ + private DictionaryService dictionaryService; + + private Constraint nameConstraint; + + // namespaceURI of the constraint + private String namespaceURI = NamespaceService.CONTENT_MODEL_1_0_URI; + + //constraint local name + private String constraintLocalName ="filename"; + + public void setNamespaceURI(String namespaceURI) + { + this.namespaceURI = namespaceURI; + } + + public void setConstraintLocalName(String constraintLocalName) + { + this.constraintLocalName = constraintLocalName; + } + + public DictionaryService getDictionaryService() + { + return dictionaryService; + } + + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + /** + * Loads filename constraint from dictionary + */ + @Override + public void afterPropertiesSet() throws Exception + { + PropertyCheck.mandatory(this, "dictionaryService", dictionaryService); + + QName qNameConstraint = QName.createQName(namespaceURI, constraintLocalName); + ConstraintDefinition constraintDef = dictionaryService.getConstraint(qNameConstraint); + if (constraintDef == null) + { + throw new AlfrescoRuntimeException("Constraint definition does not exist: " + qNameConstraint); + } + nameConstraint = constraintDef.getConstraint(); + if (nameConstraint == null) + { + throw new AlfrescoRuntimeException("Constraint does not exist: " + qNameConstraint); + } + } + + public void evaluate(Object value) + { + nameConstraint.evaluate(value); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/NoOpConstraint.java b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/NoOpConstraint.java new file mode 100644 index 0000000000..ae14340e61 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/NoOpConstraint.java @@ -0,0 +1,41 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary.constraint; + +/** + * A No operation constraint, it does nothing + * @author Gethin James + */ +public class NoOpConstraint extends AbstractConstraint +{ + + @Override + protected void evaluateSingleValue(Object value) + { + //No operation, it does nothing + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/NumericRangeConstraint.java b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/NumericRangeConstraint.java new file mode 100644 index 0000000000..c0f6618901 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/NumericRangeConstraint.java @@ -0,0 +1,156 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary.constraint; + +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.service.cmr.dictionary.ConstraintException; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; + +/** + * Constraint implementation that ensures that the value is a numeric value bewteen a given + * minimum and maximum value. If a minimum or maximum value are not provided, then the JAVA + * Double's {@link Double#MIN_VALUE minimum value} or {@link Double#MAX_VALUE maximum value} + * are assumed. + * + * @see #setMinValue(double) + * @see #setMaxValue(double) + * @see java.lang.Double#parseDouble(java.lang.String) + * + * @author Derek Hulley + */ +public class NumericRangeConstraint extends AbstractConstraint +{ + private static final String ERR_INVALID_MIN_VALUE = "d_dictionary.constraint.numeric_range.invalid_min_value"; + private static final String ERR_INVALID_MAX_VALUE = "d_dictionary.constraint.numeric_range.invalid_max_value"; + private static final String ERR_NON_NUMERIC = "d_dictionary.constraint.numeric_range.non_numeric"; + private static final String ERR_OUT_OF_RANGE = "d_dictionary.constraint.numeric_range.out_of_range"; + + private double minValue = Double.MIN_VALUE; + private double maxValue = Double.MAX_VALUE; + + @Override + public String getType() + { + return "MINMAX"; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(80); + sb.append("NumericRangeConstraint") + .append("[ minValue=").append(minValue) + .append(", maxValue=").append(maxValue) + .append("]"); + return sb.toString(); + } + + /** + * @return Returns the minimum value allowed by the constraint + */ + public double getMinValue() + { + return minValue; + } + + /** + * Set the minimum value allowed, which can be any value between + * {@link Double#MIN_VALUE} and {@link Double#MAX_VALUE}. + * + * @param minValue the minimum value allowed by the constraint + */ + public void setMinValue(double minValue) + { + if (minValue > this.maxValue) + { + throw new DictionaryException(ERR_INVALID_MIN_VALUE, minValue); + } + this.minValue = minValue; + } + + /** + * @return Returns the minimum value allowed by the constraint + */ + public double getMaxValue() + { + return maxValue; + } + + /** + * Set the maximum value allowed, which can be any value between + * {@link Double#MIN_VALUE} and {@link Double#MAX_VALUE}. + * + * @param maxValue the minimum value allowed by the constraint + */ + public void setMaxValue(double maxValue) + { + if (maxValue < this.minValue) + { + throw new DictionaryException(ERR_INVALID_MAX_VALUE, maxValue); + } + this.maxValue = maxValue; + } + + @Override + public Map getParameters() + { + Map params = new HashMap(2); + + params.put("minValue", this.minValue); + params.put("maxValue", this.maxValue); + + return params; + } + + protected void evaluateSingleValue(Object value) + { + // ensure that the value can be converted to a double + double checkValue = Double.NaN; + try + { + checkValue = DefaultTypeConverter.INSTANCE.doubleValue(value); + } + catch (NumberFormatException e) + { + throw new ConstraintException(ERR_NON_NUMERIC, value); + } + + // Infinity and NaN cannot match + if (Double.isInfinite(checkValue) || Double.isNaN(checkValue)) + { + throw new ConstraintException(ERR_OUT_OF_RANGE, checkValue, minValue, maxValue); + } + + // Check that the value is in range + if (checkValue > maxValue || checkValue < minValue) + { + throw new ConstraintException(ERR_OUT_OF_RANGE, checkValue, minValue, maxValue); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/RegexConstraint.java b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/RegexConstraint.java new file mode 100644 index 0000000000..a8721fd08a --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/RegexConstraint.java @@ -0,0 +1,162 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary.constraint; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.springframework.extensions.surf.util.I18NUtil; +import org.alfresco.service.cmr.dictionary.ConstraintException; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; + +/** + * Constraint implementation that performs regular expression comparisons. + * Where possible, the {@link org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter type converter} + * will be used to first convert the value to a String, so the evaluation + * will be against the value's String equivalent. + *

+ * The failure condition can be changed to occur either on a match or on a non-match by using + * the {@link #setRequiresMatch(boolean) requiresMatch} property. The default is true, i.e. + * failures will occur if the object value does not match the given expression. + * + * @see java.lang.String#matches(java.lang.String) + * @see java.util.regex.Pattern + * + * @author Derek Hulley + */ +public class RegexConstraint extends AbstractConstraint +{ + public static final String CONSTRAINT_REGEX_NO_MATCH = "d_dictionary.constraint.regex.no_match"; + public static final String CONSTRAINT_REGEX_MATCH = "d_dictionary.constraint.regex.match"; + public static final String CONSTRAINT_REGEX_MSG_PREFIX = "d_dictionary.constraint.regex.error."; + + private String expression; + private Pattern patternMatcher; + private boolean requiresMatch = true; + + /** + * {@inheritDoc} + */ + public String getType() + { + return "REGEX"; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(80); + sb.append("RegexConstraint") + .append("[ expression=").append(expression) + .append(", requiresMatch=").append(requiresMatch) + .append("]"); + return sb.toString(); + } + + /** + * @return Returns the regular expression similar to the {@link String#matches(java.lang.String)} + */ + public String getExpression() + { + return expression; + } + + /** + * Set the regular expression used to evaluate String values + * @param expression regular expression similar to the {@link String#matches(java.lang.String)} argument + */ + public void setExpression(String expression) + { + this.expression = expression; + } + + /** + * @return Returns true if the value must match the regular expression + * or false if the value must not match the regular expression + */ + public boolean getRequiresMatch() + { + return requiresMatch; + } + + /** + * Set whether the regular expression must be matched or not + * + * @param requiresMatch Set to true if the value must match the regular expression + * or false if the value must not match the regular expression + */ + public void setRequiresMatch(boolean requiresMatch) + { + this.requiresMatch = requiresMatch; + } + + @Override + public Map getParameters() + { + Map params = new HashMap(2); + + params.put("expression", this.expression); + params.put("requiresMatch", this.requiresMatch); + + return params; + } + + @Override + public void initialize() + { + checkPropertyNotNull("expression", expression); + + this.patternMatcher = Pattern.compile(expression); + } + + protected void evaluateSingleValue(Object value) + { + // convert the value to a String + String valueStr = DefaultTypeConverter.INSTANCE.convert(String.class, value); + Matcher matcher = patternMatcher.matcher(valueStr); + boolean matches = matcher.matches(); + if (matches != requiresMatch) + { + // Look for a message corresponding to this constraint name + String messageId = CONSTRAINT_REGEX_MSG_PREFIX + getShortName(); + if (I18NUtil.getMessage(messageId, value) != null) + { + throw new ConstraintException(messageId, value); + } + // Otherwise, fall back to a generic (but unfriendly) message + else if (requiresMatch) + { + throw new ConstraintException(RegexConstraint.CONSTRAINT_REGEX_NO_MATCH, value, expression); + } + else + { + throw new ConstraintException(RegexConstraint.CONSTRAINT_REGEX_MATCH, value, expression); + } + } + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/RegisteredConstraint.java b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/RegisteredConstraint.java new file mode 100644 index 0000000000..ac59c7584a --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/RegisteredConstraint.java @@ -0,0 +1,133 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary.constraint; + +import java.util.List; +import java.util.Map; + +import org.alfresco.service.cmr.dictionary.Constraint; +import org.alfresco.service.cmr.dictionary.DictionaryException; + +/** + * Constraint implementation that defers to constraints registered with the + * static instance of the {@link ConstraintRegistry}. + * + * @author Derek Hulley + */ +public final class RegisteredConstraint implements Constraint +{ + private static final String ERR_NAME_NOT_REGISTERED = "d_dictionary.constraint.registered.not_registered"; + + private String shortName; + private String registeredName; + + public RegisteredConstraint() + { + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(80); + sb.append("RegisteredConstraint") + .append("[ registeredName=").append(registeredName) + .append(", constraint=").append(ConstraintRegistry.getInstance().getConstraint(registeredName)) + .append("]"); + return sb.toString(); + } + + public String getShortName() + { + return shortName; + } + + public void setShortName(String shortName) + { + this.shortName = shortName; + } + + /** + * Set the name of the constraint that will be used to look up the constraint + * that will be delegated to. + */ + public void setRegisteredName(String registeredName) + { + this.registeredName = registeredName; + } + + public void initialize() + { + if (registeredName == null) + { + throw new DictionaryException(AbstractConstraint.ERR_PROP_NOT_SET, "registeredName"); + } + } + + /** + * @return the constraint that matches the registered name + */ + public Constraint getRegisteredConstraint() + { + Constraint constraint = ConstraintRegistry.getInstance().getConstraint(registeredName); + if (constraint == null) + { + throw new DictionaryException(ERR_NAME_NOT_REGISTERED, registeredName); + } + return constraint; + } + + /** + * Defers to the registered constraint + */ + public String getType() + { + return getRegisteredConstraint().getType(); + } + + /** + * Defers to the registered constraint + */ + public String getTitle() + { + return getRegisteredConstraint().getTitle(); + } + + /** + * Defers to the registered constraint + */ + public Map getParameters() + { + return getRegisteredConstraint().getParameters(); + } + + /** + * Defers to the registered constraint + */ + public void evaluate(Object value) + { + getRegisteredConstraint().evaluate(value); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/StringLengthConstraint.java b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/StringLengthConstraint.java new file mode 100644 index 0000000000..003c921c53 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/constraint/StringLengthConstraint.java @@ -0,0 +1,155 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary.constraint; + +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.service.cmr.dictionary.ConstraintException; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.service.cmr.repository.datatype.TypeConversionException; + +/** + * Constraint implementation that ensures that the length of the String value. + * + * @see #setMinLength(int) + * @see #setMaxLength(int) + * + * @author Derek Hulley + */ +public class StringLengthConstraint extends AbstractConstraint +{ + private static final String ERR_INVALID_MIN_LENGTH = "d_dictionary.constraint.string_length.invalid_min_length"; + private static final String ERR_INVALID_MAX_LENGTH = "d_dictionary.constraint.string_length.invalid_max_length"; + private static final String ERR_NON_STRING = "d_dictionary.constraint.string_length.non_string"; + private static final String ERR_INVALID_LENGTH = "d_dictionary.constraint.string_length.invalid_length"; + + private int minLength = 0; + private int maxLength = Integer.MAX_VALUE; + + /** + * {@inheritDoc} + */ + @Override + public String getType() + { + return "LENGTH"; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(80); + sb.append("StringLengthConstraint") + .append("[ minLength=").append(minLength) + .append(", maxLength=").append(maxLength) + .append("]"); + return sb.toString(); + } + + /** + * @return Returns the minimum number of characters allowed + */ + public int getMinLength() + { + return minLength; + } + + /** + * Set the minimum number of characters allowed. Valid values are in + * the range [0, {@link Integer#MAX_VALUE}]. + * + * @param minLength the minimum numbers of characters allowed + */ + public void setMinLength(int minLength) + { + if (minLength > this.maxLength || minLength < 0) + { + throw new DictionaryException(ERR_INVALID_MIN_LENGTH, minLength); + } + this.minLength = minLength; + } + + /** + * @return Returns the maximum number of characters allowed + */ + public int getMaxLength() + { + return maxLength; + } + + /** + * Set the maximum number of characters allowed. Valid values are in + * the range [0, {@link Integer#MAX_VALUE}]. + * + * @param maxLength the minimum numbers of characters allowed + */ + public void setMaxLength(int maxLength) + { + if (maxLength < this.minLength) + { + throw new DictionaryException(ERR_INVALID_MAX_LENGTH, maxLength); + } + this.maxLength = maxLength; + } + + @Override + public Map getParameters() + { + Map params = new HashMap(2); + + params.put("minLength", this.minLength); + params.put("maxLength", this.maxLength); + + return params; + } + + protected void evaluateSingleValue(Object value) + { + // ensure that the value can be converted to a String + String checkValue = null; + try + { + checkValue = DefaultTypeConverter.INSTANCE.convert(String.class, value); + } + catch (TypeConversionException e) + { + throw new ConstraintException(ERR_NON_STRING, value); + } + + // Check that the value length + int length = checkValue.length(); + if (length > maxLength || length < minLength) + { + if (length > 20) + { + checkValue = checkValue.substring(0, 17) + "..."; + } + throw new ConstraintException(ERR_INVALID_LENGTH, checkValue, minLength, maxLength); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/dictionary/m2binding.xml b/data-model/src/main/java/org/alfresco/repo/dictionary/m2binding.xml new file mode 100644 index 0000000000..98fc44169f --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/dictionary/m2binding.xml @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/repo/i18n/StaticMessageLookup.java b/data-model/src/main/java/org/alfresco/repo/i18n/StaticMessageLookup.java new file mode 100644 index 0000000000..b605394aa6 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/i18n/StaticMessageLookup.java @@ -0,0 +1,84 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.i18n; + +import java.util.Locale; + +import org.alfresco.service.NotAuditable; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * A {@link MessageLookup} that retrieves messages from a resource bundle in the classpath. + */ +public class StaticMessageLookup implements MessageLookup +{ + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.i18n.MessageLookup#getMessage(java.lang.String) + */ + @Override + @NotAuditable + public String getMessage(String messageKey) + { + return I18NUtil.getMessage(messageKey); + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.i18n.MessageLookup#getMessage(java.lang.String, java.util.Locale) + */ + @Override + @NotAuditable + public String getMessage(String messageKey, Locale locale) + { + return I18NUtil.getMessage(messageKey, locale); + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.i18n.MessageLookup#getMessage(java.lang.String, java.lang.Object[]) + */ + @Override + @NotAuditable + public String getMessage(String messageKey, Object... params) + { + return I18NUtil.getMessage(messageKey, params); + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.i18n.MessageLookup#getMessage(java.lang.String, java.util.Locale, + * java.lang.Object[]) + */ + @Override + @NotAuditable + public String getMessage(String messageKey, Locale locale, Object... params) + { + return I18NUtil.getMessage(messageKey, locale, params); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/index/shard/Floc.java b/data-model/src/main/java/org/alfresco/repo/index/shard/Floc.java new file mode 100644 index 0000000000..d0e18008bf --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/index/shard/Floc.java @@ -0,0 +1,230 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.index.shard; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.HashSet; + +import org.alfresco.service.cmr.repository.StoreRef; + +/** + * @author Andy + * + */ +public class Floc implements Serializable +{ + private static final long serialVersionUID = 3198471269440656171L; + + private HashSet storeRefs = new HashSet(); + + private int numberOfShards; + + ShardMethodEnum shardMethod; + + private String template; + + private boolean hasContent; + + private HashMap propertyBag = new HashMap(); + + /** + * + */ + public Floc() + { + } + + /** + * @return the storeRefs + */ + public HashSet getStoreRefs() + { + return storeRefs; + } + + /** + * @param storeRefs the storeRefs to set + */ + public void setStoreRefs(HashSet storeRefs) + { + this.storeRefs = storeRefs; + } + + /** + * @return the numberOfShards + */ + public int getNumberOfShards() + { + return numberOfShards; + } + + /** + * @param numberOfShards the numberOfShards to set + */ + public void setNumberOfShards(int numberOfShards) + { + this.numberOfShards = numberOfShards; + } + + /** + * @return the shardMethod + */ + public ShardMethodEnum getShardMethod() + { + return shardMethod; + } + + /** + * @param shardMethod the shardMethod to set + */ + public void setShardMethod(ShardMethodEnum shardMethod) + { + this.shardMethod = shardMethod; + } + + /** + * @return the template + */ + public String getTemplate() + { + return template; + } + + /** + * @param template the template to set + */ + public void setTemplate(String template) + { + this.template = template; + } + + /** + * @return the hasContent + */ + public boolean hasContent() + { + return hasContent; + } + + /** + * @param hasContent the hasContent to set + */ + public void setHasContent(boolean hasContent) + { + this.hasContent = hasContent; + } + + /** + * @return the propertyBag + */ + public HashMap getPropertyBag() + { + return propertyBag; + } + + /** + * @param propertyBag the propertyBag to set + */ + public void setPropertyBag(HashMap propertyBag) + { + this.propertyBag = propertyBag; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + (hasContent ? 1231 : 1237); + result = prime * result + numberOfShards; + result = prime * result + ((propertyBag == null) ? 0 : propertyBag.hashCode()); + result = prime * result + ((shardMethod == null) ? 0 : shardMethod.hashCode()); + result = prime * result + ((storeRefs == null) ? 0 : storeRefs.hashCode()); + result = prime * result + ((template == null) ? 0 : template.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Floc other = (Floc) obj; + if (hasContent != other.hasContent) + return false; + if (numberOfShards != other.numberOfShards) + return false; + if (propertyBag == null) + { + if (other.propertyBag != null) + return false; + } + else if (!propertyBag.equals(other.propertyBag)) + return false; + if (shardMethod != other.shardMethod) + return false; + if (storeRefs == null) + { + if (other.storeRefs != null) + return false; + } + else if (!storeRefs.equals(other.storeRefs)) + return false; + if (template == null) + { + if (other.template != null) + return false; + } + else if (!template.equals(other.template)) + return false; + return true; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() + { + return "Floc [storeRefs=" + + storeRefs + ", numberOfShards=" + numberOfShards + ", shardMethod=" + shardMethod + ", template=" + template + ", hasContent=" + hasContent + ", propertyBag=" + + propertyBag + "]"; + } + + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/index/shard/Shard.java b/data-model/src/main/java/org/alfresco/repo/index/shard/Shard.java new file mode 100644 index 0000000000..72f6f94dbe --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/index/shard/Shard.java @@ -0,0 +1,128 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.index.shard; + +import java.io.Serializable; + +/** + * @author Andy + * + */ +public class Shard implements Serializable +{ + private static final long serialVersionUID = -7255962796619754211L; + + private Floc floc; + + private int instance; + + public Shard() + { + + } + + /** + * @return the floc + */ + public Floc getFloc() + { + return floc; + } + + /** + * @param floc the floc to set + */ + public void setFloc(Floc floc) + { + this.floc = floc; + } + + /** + * @return the instance + */ + public int getInstance() + { + return instance; + } + + /** + * @param instance the instance to set + */ + public void setInstance(int instance) + { + this.instance = instance; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((floc == null) ? 0 : floc.hashCode()); + result = prime * result + instance; + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Shard other = (Shard) obj; + if (floc == null) + { + if (other.floc != null) + return false; + } + else if (!floc.equals(other.floc)) + return false; + if (instance != other.instance) + return false; + return true; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() + { + return "Shard [floc=" + floc + ", instance=" + instance + "]"; + } + + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/index/shard/ShardInstance.java b/data-model/src/main/java/org/alfresco/repo/index/shard/ShardInstance.java new file mode 100644 index 0000000000..348602d6d2 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/index/shard/ShardInstance.java @@ -0,0 +1,187 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.index.shard; + +import java.io.Serializable; + + +/** + * @author Andy + * + */ +public class ShardInstance implements Serializable +{ + private static final long serialVersionUID = -3407675092111933581L; + + private Shard shard; + + private String baseUrl; + + private int port; + + private String hostName; + + public ShardInstance() + { + } + + /** + * @return the shard + */ + public Shard getShard() + { + return shard; + } + + /** + * @param shard the shard to set + */ + public void setShard(Shard shard) + { + this.shard = shard; + } + + /** + * @return the baseUrl + */ + public String getBaseUrl() + { + return baseUrl; + } + + /** + * @param baseUrl the baseUrl to set + */ + public void setBaseUrl(String baseUrl) + { + if((baseUrl != null) && baseUrl.endsWith("/")) + { + this.baseUrl = baseUrl.substring(0, baseUrl.length()-1); + } + else + { + this.baseUrl = baseUrl; + } + } + + /** + * @return the port + */ + public int getPort() + { + return port; + } + + /** + * @param port the port to set + */ + public void setPort(int port) + { + this.port = port; + } + + /** + * @return the hostName + */ + public String getHostName() + { + return hostName; + } + + /** + * @param hostName the hostName to set + */ + public void setHostName(String hostName) + { + this.hostName = hostName; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((baseUrl == null) ? 0 : baseUrl.hashCode()); + result = prime * result + ((hostName == null) ? 0 : hostName.hashCode()); + result = prime * result + port; + result = prime * result + ((shard == null) ? 0 : shard.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ShardInstance other = (ShardInstance) obj; + if (baseUrl == null) + { + if (other.baseUrl != null) + return false; + } + else if (!baseUrl.equals(other.baseUrl)) + return false; + if (hostName == null) + { + if (other.hostName != null) + return false; + } + else if (!hostName.equals(other.hostName)) + return false; + if (port != other.port) + return false; + if (shard == null) + { + if (other.shard != null) + return false; + } + else if (!shard.equals(other.shard)) + return false; + return true; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() + { + return "ShardInstance [shard=" + shard + ", baseUrl=" + baseUrl + ", port=" + port + ", hostName=" + hostName + "]"; + } + + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/index/shard/ShardMethodEnum.java b/data-model/src/main/java/org/alfresco/repo/index/shard/ShardMethodEnum.java new file mode 100644 index 0000000000..c5eae317fd --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/index/shard/ShardMethodEnum.java @@ -0,0 +1,82 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.index.shard; +/** + * Enum that details sharding type + * @author Andy + * @author Michael Suzuki + * + */ +public enum ShardMethodEnum +{ + MOD_ACL_ID, + ACL_ID, + DB_ID, + DB_ID_RANGE, + EXPLICIT_ID, + DATE, + UNKOWN, + PROPERTY; + + public static ShardMethodEnum getShardMethod(String shardMethod) + { + if(shardMethod == null) + { + return UNKOWN; + } + ShardMethodEnum shardMethodEnum; + switch (shardMethod) + { + //MOD_ACL_ID legacy acl used in Alfresco 5.1 + case "MOD_ACL_ID": + shardMethodEnum = MOD_ACL_ID; + break; + //ACL id based on murmur hash. + case "ACL_ID": + shardMethodEnum = ACL_ID; + break; + case "DB_ID": + shardMethodEnum = DB_ID; + break; + case "DB_ID_RANGE": + shardMethodEnum = DB_ID_RANGE; + break; + case "DATE": + shardMethodEnum = DATE; + break; + case "PROPERTY": + shardMethodEnum = PROPERTY; + break; + case "EXPLICIT_ID": + shardMethodEnum = EXPLICIT_ID; + break; + default: + shardMethodEnum = UNKOWN; + break; + } + return shardMethodEnum; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/index/shard/ShardState.java b/data-model/src/main/java/org/alfresco/repo/index/shard/ShardState.java new file mode 100644 index 0000000000..133c5bbd0d --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/index/shard/ShardState.java @@ -0,0 +1,209 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.index.shard; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.HashSet; + +import org.alfresco.service.cmr.repository.StoreRef; + +/** + * Store shard state for auto discovery + * + * @author Andy + * + */ +public class ShardState implements Serializable +{ + private static final long serialVersionUID = -5961621567026938963L; + + ShardInstance shardInstance; + + private boolean isMaster; + + private long lastUpdated; + + private long lastIndexedChangeSetId; + + private long lastIndexedTxCommitTime = 0; + + private long lastIndexedTxId = 0; + + private long lastIndexedChangeSetCommitTime = 0; + + + private HashMap propertyBag = new HashMap(); + + public ShardState() + { + } + + /** + * @return the shardInstance + */ + public ShardInstance getShardInstance() + { + return shardInstance; + } + + /** + * @param shardInstance the shardInstance to set + */ + public void setShardInstance(ShardInstance shardInstance) + { + this.shardInstance = shardInstance; + } + + /** + * @return the isMaster + */ + public boolean isMaster() + { + return isMaster; + } + + /** + * @param isMaster the isMaster to set + */ + public void setMaster(boolean isMaster) + { + this.isMaster = isMaster; + } + + /** + * @return the propertyBag + */ + public HashMap getPropertyBag() + { + return propertyBag; + } + + /** + * @param propertyBag the propertyBag to set + */ + public void setPropertyBag(HashMap propertyBag) + { + this.propertyBag = propertyBag; + } + + + /** + * @return the lastUpdated + */ + public long getLastUpdated() + { + return lastUpdated; + } + + /** + * @param lastUpdated the lastUpdated to set + */ + public void setLastUpdated(long lastUpdated) + { + this.lastUpdated = lastUpdated; + } + + /** + * @return the lastIndexedChangeSetId + */ + public long getLastIndexedChangeSetId() + { + return lastIndexedChangeSetId; + } + + /** + * @param lastIndexedChangeSetId the lastIndexedChangeSetId to set + */ + public void setLastIndexedChangeSetId(long lastIndexedChangeSetId) + { + this.lastIndexedChangeSetId = lastIndexedChangeSetId; + } + + /** + * @return the lastIndexedTxCommitTime + */ + public long getLastIndexedTxCommitTime() + { + return lastIndexedTxCommitTime; + } + + /** + * @param lastIndexedTxCommitTime the lastIndexedTxCommitTime to set + */ + public void setLastIndexedTxCommitTime(long lastIndexedTxCommitTime) + { + this.lastIndexedTxCommitTime = lastIndexedTxCommitTime; + } + + /** + * @return the lastIndexedTxId + */ + public long getLastIndexedTxId() + { + return lastIndexedTxId; + } + + /** + * @param lastIndexedTxId the lastIndexedTxId to set + */ + public void setLastIndexedTxId(long lastIndexedTxId) + { + this.lastIndexedTxId = lastIndexedTxId; + } + + /** + * @return the lastIndexedChangeSetCommitTime + */ + public long getLastIndexedChangeSetCommitTime() + { + return lastIndexedChangeSetCommitTime; + } + + /** + * @param lastIndexedChangeSetCommitTime the lastIndexedChangeSetCommitTime to set + */ + public void setLastIndexedChangeSetCommitTime(long lastIndexedChangeSetCommitTime) + { + this.lastIndexedChangeSetCommitTime = lastIndexedChangeSetCommitTime; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() + { + return "ShardState [shardInstance=" + + shardInstance + ", isMaster=" + isMaster + ", lastUpdated=" + lastUpdated + ", lastIndexedChangeSetId=" + lastIndexedChangeSetId + ", lastIndexedTxCommitTime=" + + lastIndexedTxCommitTime + ", lastIndexedTxId=" + lastIndexedTxId + ", lastIndexedChangeSetCommitTime=" + lastIndexedChangeSetCommitTime + ", propertyBag=" + + propertyBag + "]"; + } + + + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/index/shard/ShardStateBuilder.java b/data-model/src/main/java/org/alfresco/repo/index/shard/ShardStateBuilder.java new file mode 100644 index 0000000000..66ccb49c09 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/index/shard/ShardStateBuilder.java @@ -0,0 +1,357 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +// CHECKSTYLE:OFF +/** + * Source code generated by Fluent Builders Generator + * Do not modify this file + * See generator home page at: http://code.google.com/p/fluent-builders-generator-eclipse-plugin/ + */ + +package org.alfresco.repo.index.shard; + +import java.util.HashMap; +import java.util.HashSet; +import org.alfresco.service.cmr.repository.StoreRef; + +public class ShardStateBuilder extends ShardStateBuilderBase +{ + public static ShardStateBuilder shardState() + { + return new ShardStateBuilder(); + } + + public ShardStateBuilder() + { + super(new ShardState()); + } + + public ShardState build() + { + return getInstance(); + } +} + +class ShardStateBuilderBase> +{ + private ShardState instance; + + protected ShardStateBuilderBase(ShardState aInstance) + { + instance = aInstance; + } + + protected ShardState getInstance() + { + return instance; + } + + @SuppressWarnings("unchecked") + public GeneratorT withShardInstance(ShardInstance aValue) + { + instance.setShardInstance(aValue); + + return (GeneratorT) this; + } + + public ShardInstanceShardInstanceBuilder withShardInstance() + { + ShardInstance obj = new ShardInstance(); + + withShardInstance(obj); + + return new ShardInstanceShardInstanceBuilder(obj); + } + + @SuppressWarnings("unchecked") + public GeneratorT withMaster(boolean aValue) + { + instance.setMaster(aValue); + + return (GeneratorT) this; + } + + @SuppressWarnings("unchecked") + public GeneratorT withPropertyBag(HashMap aValue) + { + instance.setPropertyBag(aValue); + + return (GeneratorT) this; + } + + @SuppressWarnings("unchecked") + public GeneratorT withLastUpdated(long aValue) + { + instance.setLastUpdated(aValue); + + return (GeneratorT) this; + } + + @SuppressWarnings("unchecked") + public GeneratorT withLastIndexedChangeSetId(long aValue) + { + instance.setLastIndexedChangeSetId(aValue); + + return (GeneratorT) this; + } + + @SuppressWarnings("unchecked") + public GeneratorT withLastIndexedTxCommitTime(long aValue) + { + instance.setLastIndexedTxCommitTime(aValue); + + return (GeneratorT) this; + } + + @SuppressWarnings("unchecked") + public GeneratorT withLastIndexedTxId(long aValue) + { + instance.setLastIndexedTxId(aValue); + + return (GeneratorT) this; + } + + @SuppressWarnings("unchecked") + public GeneratorT withLastIndexedChangeSetCommitTime(long aValue) + { + instance.setLastIndexedChangeSetCommitTime(aValue); + + return (GeneratorT) this; + } + + public class ShardInstanceShardInstanceBuilder extends ShardInstanceBuilderBase + { + public ShardInstanceShardInstanceBuilder(ShardInstance aInstance) + { + super(aInstance); + } + + @SuppressWarnings("unchecked") + public GeneratorT endShardInstance() + { + return (GeneratorT) ShardStateBuilderBase.this; + } + } + + public static class ShardInstanceBuilderBase> + { + private ShardInstance instance; + + protected ShardInstanceBuilderBase(ShardInstance aInstance) + { + instance = aInstance; + } + + protected ShardInstance getInstance() + { + return instance; + } + + @SuppressWarnings("unchecked") + public GeneratorT withShard(Shard aValue) + { + instance.setShard(aValue); + + return (GeneratorT) this; + } + + public ShardShardBuilder withShard() + { + Shard obj = new Shard(); + + withShard(obj); + + return new ShardShardBuilder(obj); + } + + @SuppressWarnings("unchecked") + public GeneratorT withBaseUrl(String aValue) + { + instance.setBaseUrl(aValue); + + return (GeneratorT) this; + } + + @SuppressWarnings("unchecked") + public GeneratorT withPort(int aValue) + { + instance.setPort(aValue); + + return (GeneratorT) this; + } + + @SuppressWarnings("unchecked") + public GeneratorT withHostName(String aValue) + { + instance.setHostName(aValue); + + return (GeneratorT) this; + } + + public class ShardShardBuilder extends ShardBuilderBase + { + public ShardShardBuilder(Shard aInstance) + { + super(aInstance); + } + + @SuppressWarnings("unchecked") + public GeneratorT endShard() + { + return (GeneratorT) ShardInstanceBuilderBase.this; + } + } + } + + public static class ShardBuilderBase> + { + private Shard instance; + + protected ShardBuilderBase(Shard aInstance) + { + instance = aInstance; + } + + protected Shard getInstance() + { + return instance; + } + + @SuppressWarnings("unchecked") + public GeneratorT withFloc(Floc aValue) + { + instance.setFloc(aValue); + + return (GeneratorT) this; + } + + public FlocFlocBuilder withFloc() + { + Floc obj = new Floc(); + + withFloc(obj); + + return new FlocFlocBuilder(obj); + } + + @SuppressWarnings("unchecked") + public GeneratorT withInstance(int aValue) + { + instance.setInstance(aValue); + + return (GeneratorT) this; + } + + public class FlocFlocBuilder extends FlocBuilderBase + { + public FlocFlocBuilder(Floc aInstance) + { + super(aInstance); + } + + @SuppressWarnings("unchecked") + public GeneratorT endFloc() + { + return (GeneratorT) ShardBuilderBase.this; + } + } + } + + public static class FlocBuilderBase> + { + private Floc instance; + + protected FlocBuilderBase(Floc aInstance) + { + instance = aInstance; + } + + protected Floc getInstance() + { + return instance; + } + + @SuppressWarnings("unchecked") + public GeneratorT withStoreRefs(HashSet aValue) + { + instance.setStoreRefs(aValue); + + return (GeneratorT) this; + } + + @SuppressWarnings("unchecked") + public GeneratorT withAddedStoreRef(StoreRef aValue) + { + if (instance.getStoreRefs() == null) + { + instance.setStoreRefs(new HashSet()); + } + + ((HashSet) instance.getStoreRefs()).add(aValue); + + return (GeneratorT) this; + } + + @SuppressWarnings("unchecked") + public GeneratorT withNumberOfShards(int aValue) + { + instance.setNumberOfShards(aValue); + + return (GeneratorT) this; + } + + @SuppressWarnings("unchecked") + public GeneratorT withShardMethod(ShardMethodEnum aValue) + { + instance.setShardMethod(aValue); + + return (GeneratorT) this; + } + + @SuppressWarnings("unchecked") + public GeneratorT withTemplate(String aValue) + { + instance.setTemplate(aValue); + + return (GeneratorT) this; + } + + @SuppressWarnings("unchecked") + public GeneratorT withHasContent(boolean aValue) + { + instance.setHasContent(aValue); + + return (GeneratorT) this; + } + + @SuppressWarnings("unchecked") + public GeneratorT withPropertyBag(HashMap aValue) + { + instance.setPropertyBag(aValue); + + return (GeneratorT) this; + } + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/MLAnalysisMode.java b/data-model/src/main/java/org/alfresco/repo/search/MLAnalysisMode.java new file mode 100644 index 0000000000..4333df900e --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/MLAnalysisMode.java @@ -0,0 +1,931 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search; + +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +import org.alfresco.error.AlfrescoRuntimeException; + +/** + * Enum to specify how multi-lingual properties should be treate for indexing and search. Note that locale new Locale + * ("", "", "") is used to indicate all locales. + * + * @author andyh + */ +public enum MLAnalysisMode +{ + /** + * Only the exact locale is used. + */ + LOCALE_ONLY + { + public boolean includesAll() + { + return false; + } + + public boolean includesContained() + { + return false; + } + + public boolean includesContaining() + { + return false; + } + + public boolean includesExact() + { + return true; + } + + public boolean includesAllLanguageMatches() + { + return false; + } + + public boolean includesExactLanguageMatch() + { + return false; + } + + public boolean includesAllCountryMatches() + { + return false; + } + + public boolean includesExactCountryMatch() + { + return false; + } + + }, + + /** + * Only the exact locale and no locale === locale + all languages + */ + LOCALE_AND_ALL + { + public boolean includesAll() + { + return true; + } + + public boolean includesContained() + { + return false; + } + + public boolean includesContaining() + { + return false; + } + + public boolean includesExact() + { + return true; + } + + public boolean includesAllLanguageMatches() + { + return false; + } + + public boolean includesExactLanguageMatch() + { + return false; + } + + public boolean includesAllCountryMatches() + { + return false; + } + + public boolean includesExactCountryMatch() + { + return false; + } + }, + + /** + * Expand the locale to include all the locales that contain it. So "en_GB" would be "en_GB", "en", but not all + * languages "". + */ + LOCALE_AND_ALL_CONTAINING_LOCALES + { + public boolean includesAll() + { + return false; + } + + public boolean includesContained() + { + return false; + } + + public boolean includesContaining() + { + return true; + } + + public boolean includesExact() + { + return true; + } + + public boolean includesAllLanguageMatches() + { + return false; + } + + public boolean includesExactLanguageMatch() + { + return false; + } + + public boolean includesAllCountryMatches() + { + return false; + } + + public boolean includesExactCountryMatch() + { + return false; + } + }, + + /** + * Expand the locale to include all the locales that contain it. "en_GB" would be "en_GB", "en", and all "". + */ + LOCALE_AND_ALL_CONTAINING_LOCALES_AND_ALL + { + public boolean includesAll() + { + return true; + } + + public boolean includesContained() + { + return false; + } + + public boolean includesContaining() + { + return true; + } + + public boolean includesExact() + { + return true; + } + + public boolean includesAllLanguageMatches() + { + return false; + } + + public boolean includesExactLanguageMatch() + { + return false; + } + + public boolean includesAllCountryMatches() + { + return false; + } + + public boolean includesExactCountryMatch() + { + return false; + } + }, + + /** + * Expand to all the locales that are contained by this. "en" would expand to "en", "en_GB", "en_US", .... + */ + LOCALE_AND_ALL_CONTAINED_LOCALES + { + public boolean includesAll() + { + return false; + } + + public boolean includesContained() + { + return true; + } + + public boolean includesContaining() + { + return false; + } + + public boolean includesExact() + { + return true; + } + + public boolean includesAllLanguageMatches() + { + return false; + } + + public boolean includesExactLanguageMatch() + { + return false; + } + + public boolean includesAllCountryMatches() + { + return false; + } + + public boolean includesExactCountryMatch() + { + return false; + } + }, + + /** + * Just the all locale, "", === new Locale("", "", "") + */ + ALL_ONLY + { + public boolean includesAll() + { + return true; + } + + public boolean includesContained() + { + return false; + } + + public boolean includesContaining() + { + return false; + } + + public boolean includesExact() + { + return false; + } + + public boolean includesAllLanguageMatches() + { + return false; + } + + public boolean includesExactLanguageMatch() + { + return false; + } + + public boolean includesAllCountryMatches() + { + return false; + } + + public boolean includesExactCountryMatch() + { + return false; + } + }, + + /** + * All language matches. Only worry about language level matches for locale. + */ + + ALL_LANGUAGES + { + public boolean includesAll() + { + return false; + } + + public boolean includesContained() + { + return false; + } + + public boolean includesContaining() + { + return false; + } + + public boolean includesExact() + { + return false; + } + + public boolean includesAllLanguageMatches() + { + return true; + } + + public boolean includesExactLanguageMatch() + { + return false; + } + + public boolean includesAllCountryMatches() + { + return false; + } + + public boolean includesExactCountryMatch() + { + return false; + } + }, + + /** + * All language matches and ALL + */ + + ALL_LANGUAGES_AND_ALL + { + public boolean includesAll() + { + return true; + } + + public boolean includesContained() + { + return false; + } + + public boolean includesContaining() + { + return false; + } + + public boolean includesExact() + { + return false; + } + + public boolean includesAllLanguageMatches() + { + return true; + } + + public boolean includesExactLanguageMatch() + { + return false; + } + + public boolean includesAllCountryMatches() + { + return false; + } + + public boolean includesExactCountryMatch() + { + return false; + } + }, + + /** + * Exact language matches (do not include all sub varients of the language) + */ + + EXACT_LANGUAGE + { + public boolean includesAll() + { + return false; + } + + public boolean includesContained() + { + return false; + } + + public boolean includesContaining() + { + return false; + } + + public boolean includesExact() + { + return false; + } + + public boolean includesAllLanguageMatches() + { + return false; + } + + public boolean includesExactLanguageMatch() + { + return true; + } + + public boolean includesAllCountryMatches() + { + return false; + } + + public boolean includesExactCountryMatch() + { + return false; + } + }, + + /** + * Exact language matches (do not include all sub varients of the language) and ALL + */ + + EXACT_LANGUAGE_AND_ALL + { + public boolean includesAll() + { + return true; + } + + public boolean includesContained() + { + return false; + } + + public boolean includesContaining() + { + return false; + } + + public boolean includesExact() + { + return false; + } + + public boolean includesAllLanguageMatches() + { + return false; + } + + public boolean includesExactLanguageMatch() + { + return true; + } + + public boolean includesAllCountryMatches() + { + return false; + } + + public boolean includesExactCountryMatch() + { + return false; + } + }, + + /** + * Exact country matches (do not include all sub varients of the country) + */ + + EXACT_COUNRTY + { + public boolean includesAll() + { + return false; + } + + public boolean includesContained() + { + return false; + } + + public boolean includesContaining() + { + return false; + } + + public boolean includesExact() + { + return false; + } + + public boolean includesAllLanguageMatches() + { + return false; + } + + public boolean includesExactLanguageMatch() + { + return false; + } + + public boolean includesAllCountryMatches() + { + return false; + } + + public boolean includesExactCountryMatch() + { + return true; + } + }, + + /** + * Exact country matches (do not include all sub varients of the country) and ALL + */ + + EXACT_COUNTRY_AND_ALL + { + public boolean includesAll() + { + return true; + } + + public boolean includesContained() + { + return false; + } + + public boolean includesContaining() + { + return false; + } + + public boolean includesExact() + { + return false; + } + + public boolean includesAllLanguageMatches() + { + return false; + } + + public boolean includesExactLanguageMatch() + { + return false; + } + + public boolean includesAllCountryMatches() + { + return false; + } + + public boolean includesExactCountryMatch() + { + return true; + } + }, + + /** + * All country matches + */ + + ALL_COUNTRIES + { + public boolean includesAll() + { + return false; + } + + public boolean includesContained() + { + return false; + } + + public boolean includesContaining() + { + return false; + } + + public boolean includesExact() + { + return false; + } + + public boolean includesAllLanguageMatches() + { + return false; + } + + public boolean includesExactLanguageMatch() + { + return false; + } + + public boolean includesAllCountryMatches() + { + return true; + } + + public boolean includesExactCountryMatch() + { + return false; + } + }, + + /** + * All countries and ALL + */ + + ALL_COUNTRIES_AND_ALL + { + public boolean includesAll() + { + return true; + } + + public boolean includesContained() + { + return false; + } + + public boolean includesContaining() + { + return false; + } + + public boolean includesExact() + { + return false; + } + + public boolean includesAllLanguageMatches() + { + return false; + } + + public boolean includesExactLanguageMatch() + { + return false; + } + + public boolean includesAllCountryMatches() + { + return true; + } + + public boolean includesExactCountryMatch() + { + return false; + } + }; + + public static MLAnalysisMode getMLAnalysisMode(String mode) + { + for (MLAnalysisMode test : MLAnalysisMode.values()) + { + if (test.toString().equalsIgnoreCase(mode)) + { + return test; + } + } + throw new AlfrescoRuntimeException("Unknown ML Analysis mode " + mode); + } + + public abstract boolean includesAll(); + + public abstract boolean includesContained(); + + public abstract boolean includesContaining(); + + public abstract boolean includesExact(); + + public abstract boolean includesAllLanguageMatches(); + + public abstract boolean includesExactLanguageMatch(); + + public abstract boolean includesAllCountryMatches(); + + public abstract boolean includesExactCountryMatch(); + + public static Set getLocales(MLAnalysisMode mlAnalaysisMode, Locale locale, boolean withWildcards) + { + HashSet locales = new HashSet(); + + boolean l = locale.getLanguage().length() != 0; + boolean c = locale.getCountry().length() != 0; + boolean v = locale.getVariant().length() != 0; + + if (mlAnalaysisMode.includesAll()) + { + if (withWildcards) + { + locales.add(new Locale("", "", "")); + locales.add(new Locale("*", "", "")); + } + else + { + locales.add(new Locale("", "", "")); + } + + } + + if (mlAnalaysisMode.includesExact()) + { + locales.add(locale); + } + + if (mlAnalaysisMode.includesContaining()) + { + if (v) + { + Locale noVarient = new Locale(locale.getLanguage(), locale.getCountry(), ""); + locales.add(noVarient); + + Locale noCountry = new Locale(locale.getLanguage(), "", ""); + locales.add(noCountry); + } + if (c) + { + Locale noCountry = new Locale(locale.getLanguage(), "", ""); + locales.add(noCountry); + } + } + + if (mlAnalaysisMode.includesContained()) + { + // varients have not contained + if (!v) + { + if (!c) + { + if (!l) + { + // All + if (withWildcards) + { + locales.add(new Locale("", "", "")); + locales.add(new Locale("*", "", "")); + } + else + { + for (Locale toAdd : Locale.getAvailableLocales()) + { + locales.add(toAdd); + } + } + } + else + { + // All that match language + if (withWildcards) + { + locales.add(new Locale(locale.getLanguage(), "", "")); + locales.add(new Locale(locale.getLanguage(), "*", "")); + } + else + { + for (Locale toAdd : Locale.getAvailableLocales()) + { + if (locale.getLanguage().equals("") || locale.getLanguage().equals(toAdd.getLanguage())) + { + locales.add(toAdd); + } + } + } + } + } + else + { + if (withWildcards) + { + locales.add(new Locale(locale.getLanguage(), locale.getCountry(), "")); + locales.add(new Locale(locale.getLanguage(), locale.getCountry(), "*")); + } + else + { + // All that match language and country + for (Locale toAdd : Locale.getAvailableLocales()) + { + if ((locale.getLanguage().equals("") || locale.getLanguage().equals(toAdd.getLanguage())) + && (locale.getCountry().equals("") || locale.getCountry() + .equals(toAdd.getCountry()))) + { + locales.add(toAdd); + } + } + } + } + } + } + + if (mlAnalaysisMode.includesAllLanguageMatches()) + { + if (withWildcards) + { + locales.add(new Locale(locale.getLanguage(), "", "")); + locales.add(new Locale(locale.getLanguage(), "*", "")); + } + else + { + // All that match language + for (Locale toAdd : Locale.getAvailableLocales()) + { + if (locale.getLanguage().equals("") || locale.getLanguage().equals(toAdd.getLanguage())) + { + locales.add(toAdd); + } + } + } + } + + if (mlAnalaysisMode.includesExactLanguageMatch()) + { + if (withWildcards) + { + locales.add(new Locale(locale.getLanguage(), "", "")); + } + else + { + locales.add(new Locale(locale.getLanguage(), "", "")); + } + } + + if (mlAnalaysisMode.includesAllCountryMatches()) + { + if (withWildcards) + { + locales.add(new Locale(locale.getLanguage(), locale.getCountry(), "")); + if(locale.getCountry().equals("")) + { + locales.add(new Locale(locale.getLanguage(), "*", "")); + } + else + { + locales.add(new Locale(locale.getLanguage(), locale.getCountry(), "*")); + } + } + else + { + // All that match language + for (Locale toAdd : Locale.getAvailableLocales()) + { + if ((locale.getLanguage().equals("") || locale.getLanguage().equals(toAdd.getLanguage())) + && (locale.getCountry().equals("") || locale.getCountry().equals(toAdd.getCountry()))) + { + locales.add(toAdd); + } + } + } + } + + if (mlAnalaysisMode.includesExactCountryMatch()) + { + if (withWildcards) + { + if(locale.getCountry().equals("")) + { + locales.add(new Locale(locale.getLanguage(), "", "")); + locales.add(new Locale(locale.getLanguage(), "*", "")); + } + else + { + locales.add(new Locale(locale.getLanguage(), locale.getCountry(), "")); + } + + } + else + { + if (locale.getCountry().equals("")) + { + for (Locale toAdd : Locale.getAvailableLocales()) + { + if (locale.getLanguage().equals("") || locale.getLanguage().equals(toAdd.getLanguage())) + { + locales.add(toAdd); + } + } + } + else + { + locales.add(new Locale(locale.getLanguage(), locale.getCountry(), "")); + } + } + } + + return locales; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/AnalysisMode.java b/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/AnalysisMode.java new file mode 100644 index 0000000000..16fc0dd9c7 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/AnalysisMode.java @@ -0,0 +1,45 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.adaptor.lucene; + +public enum AnalysisMode +{ + DEFAULT + , + TOKENISE + , + IDENTIFIER + , + FUZZY + , + PREFIX + , + WILD + , + LIKE + ; + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneFunction.java b/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneFunction.java new file mode 100644 index 0000000000..117e74319c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneFunction.java @@ -0,0 +1,52 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.repo.search.adaptor.lucene; + +/** + * Functions that can be applied to lucene fields + * + * Currently upper and lower that perform a case insensitive match for untokenised fields. + * (If the field is tokenised the match should already be case insensitive.) + * + * @author andyh + * + */ +public enum LuceneFunction +{ + /** + * Match as if the field was converted to upper case. + */ + UPPER, + /** + * Match as if the field was converted to lower case. + */ + LOWER, + /** + * A normal lucene field match. + */ + FIELD; +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneQueryParserAdaptor.java b/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneQueryParserAdaptor.java new file mode 100644 index 0000000000..67f2c3f55c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneQueryParserAdaptor.java @@ -0,0 +1,235 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.adaptor.lucene; + +import java.util.List; + +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Ordering; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.search.SearchParameters; + +/** + * Adaptor class principally to wrap lucene parser implementations and encapsulate changes between lucene versions + * of query building. + * + * @param the query type used by the query engine implementation + * @param the sort type used by the query engine implementation + * @param the exception it throws + * + * @author Andy + * + */ +public interface LuceneQueryParserAdaptor +{ + + /** + * @param field String + * @param queryText String + * @param analysisMode AnalysisMode + * @param luceneFunction LuceneFunction + * @return Q + */ + Q getFieldQuery(String field, String queryText, AnalysisMode analysisMode, LuceneFunction luceneFunction) throws E; + + /** + * @param field String + * @param lower String + * @param upper String + * @param includeLower boolean + * @param includeUpper boolean + * @param analysisMode AnalysisMode + * @param luceneFunction LuceneFunction + * @return Q + */ + Q getRangeQuery(String field, String lower, String upper, boolean includeLower, boolean includeUpper, AnalysisMode analysisMode, LuceneFunction luceneFunction) throws E; + + + /** + * A query that matches all docs + * + * @return Q + * @throws E + */ + Q getMatchAllQuery() throws E; + + /** + * A query that matches no docs. + * + * @return Q + * @throws E + */ + Q getMatchNoneQuery() throws E; + + /** + * @param field String + * @param sqlLikeClause String + * @param analysisMode AnalysisMode + * @return Q + */ + Q getLikeQuery(String field, String sqlLikeClause, AnalysisMode analysisMode) throws E; + + /** + * @return SearchParameters + */ + SearchParameters getSearchParameters(); + + /** + * @param field String + * @return String + */ + String getSortField(String field) throws E; + + /** + * Wrap generating a potentially complex id + version query + * + * @param field String + * @param stringValue String + * @param analysisMode AnalysisMode + * @param luceneFunction LuceneFunction + * @return Q + */ + Q getIdentifierQuery(String field, String stringValue, AnalysisMode analysisMode, LuceneFunction luceneFunction) throws E; + + /** + * Wrap generating a potentially complex id + version query + * + * @param field String + * @param stringValue String + * @param analysisMode AnalysisMode + * @return Q + */ + Q getIdentifieLikeQuery(String field, String stringValue, AnalysisMode analysisMode) throws E; + + /** + * @param noLocalField String + * @return boolean + */ + boolean sortFieldExists(String noLocalField); + + /** + * @param field String + * @param value String + * @return Q + * @throws E + */ + Q getFieldQuery(String field, String value) throws E; + + /** + * @param list List + * @param functionContext FunctionEvaluationContext + * @return S + * @throws E + */ + S buildSort(List list, FunctionEvaluationContext functionContext) throws E; + + /** + * @param luceneFieldName String + * @param term String + * @param minSimilarity Float + * @return Q + * @throws E + */ + Q getFuzzyQuery(String luceneFieldName, String term, Float minSimilarity) throws E; + + /** + * Get the default field + * + * @return String + */ + String getField(); + + /** + * Get the default phrase slop + * + * @return int + */ + int getPhraseSlop(); + + /** + * @param luceneFieldName String + * @param term String + * @param analysisMode AnalysisMode + * @param slop Integer + * @param luceneFunction LuceneFunction + * @return Q + */ + Q getFieldQuery(String luceneFieldName, String term, AnalysisMode analysisMode, Integer slop, LuceneFunction luceneFunction) throws E; + + /** + * @param luceneFieldName String + * @param term String + * @param analysisMode AnalysisMode + * @return Q + */ + Q getPrefixQuery(String luceneFieldName, String term, AnalysisMode analysisMode) throws E; + + /** + * @param luceneFieldName String + * @param first String + * @param last String + * @param slop int + * @param inOrder boolean + * @return Q + */ + Q getSpanQuery(String luceneFieldName, String first, String last, int slop, boolean inOrder) throws E; + + /** + * @param luceneFieldName String + * @param term String + * @param mode AnalysisMode + * @return Q + */ + Q getWildcardQuery(String luceneFieldName, String term, AnalysisMode mode) throws E; + + /** + * Invert a query - add a mandatory must not match anything query alnogside + * + * @param query Q + * @return Q + */ + Q getNegatedQuery(Q query) throws E; + + /** + * Utility to build conjunctions, disjunctions and negation + * @return LuceneQueryParserExpressionAdaptor + */ + LuceneQueryParserExpressionAdaptor getExpressionAdaptor(); + + /** + * A query that matches all alfresco nodes (not extra stuff that may be in the underlying index) + * + * @return Q + */ + Q getMatchAllNodesQuery(); + + /** + * @param field String + * @param propertyDef PropertyDefinition + * @return String + */ + String getDatetimeSortField(String field, PropertyDefinition propertyDef); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneQueryParserExpressionAdaptor.java b/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneQueryParserExpressionAdaptor.java new file mode 100644 index 0000000000..8a1209748a --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/LuceneQueryParserExpressionAdaptor.java @@ -0,0 +1,42 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.adaptor.lucene; + +/** + * @author Andy + * + */ +public interface LuceneQueryParserExpressionAdaptor +{ + public void addRequired(Q q) throws E; + public void addExcluded(Q q) throws E; + public void addOptional(Q q) throws E; + public void addRequired(Q q, float boost) throws E; + public void addExcluded(Q q, float boost) throws E; + public void addOptional(Q q, float boost) throws E; + public Q getQuery() throws E; + public Q getNegatedQuery() throws E; +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/QueryConstants.java b/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/QueryConstants.java new file mode 100644 index 0000000000..ba5faf3e5d --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/adaptor/lucene/QueryConstants.java @@ -0,0 +1,209 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.adaptor.lucene; + +/** + * This class defines + * 1) all the non-property fields available to query + * 2) all the extensions to properties + * + * @author Andy + * + */ +public interface QueryConstants +{ + public static final String FIELD_NO_LOCALE_SUFFIX = ".no_locale"; + + public static final String FIELD_SORT_SUFFIX = ".sort"; + + public static final String FIELD_LOCALE_SUFFIX = ".locale"; + + public static final String FIELD_SIZE_SUFFIX = ".size"; + + public static final String FIELD_MIMETYPE_SUFFIX = ".mimetype"; + + public static final String FIELD_FTSSTATUS = "FTSSTATUS"; + + public static final String FIELD_FTSREF = "FTSREF"; + + public static final String FIELD_ISNOTNULL = "ISNOTNULL"; + + public static final String FIELD_ISNULL = "ISNULL"; + + public static final String FIELD_ISUNSET = "ISUNSET"; + + public static final String FIELD_EXISTS = "EXISTS"; + + public static final String FIELD_ALL = "ALL"; + + public static final String PROPERTY_FIELD_PREFIX = "@"; + + public static final String FIELD_EXACTASPECT = "EXACTASPECT"; + + public static final String FIELD_EXACTTYPE = "EXACTTYPE"; + + public static final String FIELD_TYPE = "TYPE"; + + public static final String FIELD_ASPECT = "ASPECT"; + + public static final String FIELD_CLASS = "CLASS"; + + public static final String FIELD_ASSOCTYPEQNAME = "ASSOCTYPEQNAME"; + + public static final String FIELD_PRIMARYASSOCTYPEQNAME = "PRIMARYASSOCTYPEQNAME"; + + public static final String FIELD_QNAME = "QNAME"; + + public static final String FIELD_PRIMARYPARENT = "PRIMARYPARENT"; + + public static final String FIELD_PARENT = "PARENT"; + + /** + * @deprecated This is basically unused - you want TXID + */ + @Deprecated + public static final String FIELD_TX = "TX"; + + public static final String FIELD_ISNODE = "ISNODE"; + + public static final String FIELD_ISCONTAINER = "ISCONTAINER"; + + public static final String FIELD_ISROOT = "ISROOT"; + + public static final String FIELD_DBID = "DBID"; + + public static final String FIELD_ID = "ID"; + + public static final String FIELD_TEXT = "TEXT"; + + public static final String FIELD_PATHWITHREPEATS = "PATHWITHREPEATS"; + + public static final String FIELD_PATH = "PATH"; + + public static final String FIELD_TAG = "TAG"; + + public static final String FIELD_ACLID = "ACLID"; + + public static final String FIELD_OWNER = "OWNER"; + + public static final String FIELD_READER = "READER"; + + public static final String FIELD_DENIED = "DENIED"; + + public static final String FIELD_AUTHORITY = "AUTHORITY"; + + public static final String FIELD_OWNERSET = "OWNERSET"; + + public static final String FIELD_READERSET = "READERSET"; + + public static final String FIELD_DENYSET = "DENYSET"; + + public static final String FIELD_AUTHORITYSET = "AUTHSET"; + + public static final String FIELD_TXID = "TXID"; + public static final String FIELD_S_TXID = "S_TXID"; + + public static final String FIELD_INTXID = "INTXID"; + public static final String FIELD_S_INTXID = "S_INTXID"; + + public static final String FIELD_ACLTXID = "ACLTXID"; + public static final String FIELD_S_ACLTXID = "S_ACLTXID"; + + public static final String FIELD_INACLTXID = "INACLTXID"; + public static final String FIELD_S_INACLTXID = "S_INACLTXID"; + + public static final String FIELD_TXCOMMITTIME = "TXCOMMITTIME"; + public static final String FIELD_S_TXCOMMITTIME = "S_TXCOMMITTIME"; + + public static final String FIELD_ACLTXCOMMITTIME = "ACLTXCOMMITTIME"; + public static final String FIELD_S_ACLTXCOMMITTIME = "S_ACLTXCOMMITTIME"; + + public static final String FIELD_LINKASPECT = "LINKASPECT"; + + public static final String FIELD_ANCESTOR = "ANCESTOR"; + + public static final String FIELD_ISCATEGORY = "ISCATEGORY"; + + public static final String FIELD_ENCODING_SUFFIX = ".encoding"; + + public static final String FIELD_CONTENT_DOC_ID_SUFFIX = "contentDocId"; + + public static final String FIELD_TRANSFORMATION_EXCEPTION_SUFFIX = ".transformationException"; + + public static final String FIELD_TRANSFORMATION_TIME_SUFFIX = ".transformationTime"; + + public static final String FIELD_TRANSFORMATION_STATUS_SUFFIX = ".transformationStatus"; + + public static final String FIELD_PARENT_ASSOC_CRC = "PARENTASSOCCRC"; + + public static final String FIELD_PRIMARYASSOCQNAME = "PRIMARYASSOCQNAME"; + + public static final String FIELD_LID = "LID"; + + public static final String FIELD_CASCADE_FLAG = "int@s_@cascade"; + + public static final String FIELD_TENANT = "TENANT"; + + public static final String FIELD_EXCEPTION_MESSAGE = "EXCEPTIONMESSAGE"; + + public static final String FIELD_EXCEPTION_STACK = "EXCEPTIONSTACK"; + + public static final String FIELD_SOLR4_ID = "id"; + + public static final String FIELD_DOC_TYPE = "DOC_TYPE"; + + public static final String FIELD_SOLR_LOCALISED_UNTOKENISED_SUFFIX = ".u"; + + public static final String FIELD_SOLR_NOLOCALE_UNTOKENISED_SUFFIX = ".__.u"; + + public static final String FIELD_SOLR_NOLOCALE_TOKENISED_SUFFIX = ".__"; + + public static final String FIELD_SITE = "SITE"; + + public static final String FIELD_GEO = "GEO"; + + public static final String FIELD_NPATH = "NPATH"; + + public static final String FIELD_PNAME = "PNAME"; + + public static final String FIELD_APATH = "APATH"; + + public static final String FIELD_ANAME = "ANAME"; + + public static final String FIELD_PROPERTIES = "PROPERTIES"; + + public static final String FIELD_NULLPROPERTIES = "NULLPROPERTIES"; + + public static final String FIELD_FIELDS = "FIELDS"; + + public static final String FIELD_TAG_SUGGEST = "suggest_TAG"; + + public static final String FIELD_VERSION = "_version_"; + + public static final String FIELD_CASCADETX = "CASCADETX"; + + public static final String FIELD_FINGERPRINT = "FINGERPRINT"; +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/QueryParserUtils.java b/data-model/src/main/java/org/alfresco/repo/search/impl/QueryParserUtils.java new file mode 100644 index 0000000000..df50966487 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/QueryParserUtils.java @@ -0,0 +1,394 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl; + +import java.util.HashSet; + +import org.alfresco.repo.search.adaptor.lucene.QueryConstants; +import org.alfresco.service.cmr.dictionary.AspectDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.NamespaceException; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; + +/** + * @author Andy + * + */ +public class QueryParserUtils implements QueryConstants +{ + public static String expandQName(String defaultNameSpaceUri, NamespacePrefixResolver namespacePrefixResolver, String qnameString) + { + String fieldName = qnameString; + // Check for any prefixes and expand to the full uri + if (qnameString.charAt(0) != '{') + { + int colonPosition = qnameString.indexOf(':'); + if (colonPosition == -1) + { + // use the default namespace + fieldName = "{" + defaultNameSpaceUri + "}" + qnameString; + } + else + { + String prefix = qnameString.substring(0, colonPosition); + String uri = matchURI(namespacePrefixResolver, prefix); + if (uri == null) + { + fieldName = "{" + defaultNameSpaceUri + "}" + qnameString; + } + else + { + fieldName = "{" + uri + "}" + qnameString.substring(colonPosition + 1); + } + + } + } + return fieldName; + } + + public static String matchURI(NamespacePrefixResolver namespacePrefixResolver, String prefix) + { + HashSet prefixes = new HashSet(namespacePrefixResolver.getPrefixes()); + if (prefixes.contains(prefix)) + { + return namespacePrefixResolver.getNamespaceURI(prefix); + } + String match = null; + for (String candidate : prefixes) + { + if (candidate.equalsIgnoreCase(prefix)) + { + if (match == null) + { + match = candidate; + } + else + { + + throw new NamespaceException("Ambiguous namespace prefix " + prefix); + + } + } + } + if (match == null) + { + return null; + } + else + { + return namespacePrefixResolver.getNamespaceURI(match); + } + } + + public static ClassDefinition matchClassDefinition(String defaultNameSpaceUri, NamespacePrefixResolver namespacePrefixResolver, DictionaryService dictionaryService, String string) + { + QName search = QName.createQName(expandQName(defaultNameSpaceUri, namespacePrefixResolver, string)); + ClassDefinition classDefinition = dictionaryService.getClass(QName.createQName(expandQName(defaultNameSpaceUri, namespacePrefixResolver, string))); + QName match = null; + if (classDefinition == null) + { + for (QName definition : dictionaryService.getAllTypes()) + { + if (definition.getNamespaceURI().equalsIgnoreCase(search.getNamespaceURI())) + { + if (definition.getLocalName().equalsIgnoreCase(search.getLocalName())) + { + if (match == null) + { + match = definition; + } + else + { + throw new DictionaryException("Ambiguous data datype " + string); + } + } + } + } + for (QName definition : dictionaryService.getAllAspects()) + { + if (definition.getNamespaceURI().equalsIgnoreCase(search.getNamespaceURI())) + { + if (definition.getLocalName().equalsIgnoreCase(search.getLocalName())) + { + if (match == null) + { + match = definition; + } + else + { + throw new DictionaryException("Ambiguous data datype " + string); + } + } + } + } + } + else + { + return classDefinition; + } + if (match == null) + { + return null; + } + else + { + return dictionaryService.getClass(match); + } + } + + public static AspectDefinition matchAspectDefinition(String defaultNameSpaceUri, NamespacePrefixResolver namespacePrefixResolver, DictionaryService dictionaryService, String string) + { + QName search = QName.createQName(expandQName(defaultNameSpaceUri, namespacePrefixResolver, string)); + AspectDefinition aspectDefinition = dictionaryService.getAspect(QName.createQName(expandQName(defaultNameSpaceUri, namespacePrefixResolver, string))); + QName match = null; + if (aspectDefinition == null) + { + for (QName definition : dictionaryService.getAllAspects()) + { + if (definition.getNamespaceURI().equalsIgnoreCase(search.getNamespaceURI())) + { + if (definition.getLocalName().equalsIgnoreCase(search.getLocalName())) + { + if (match == null) + { + match = definition; + } + else + { + throw new DictionaryException("Ambiguous data datype " + string); + } + } + } + } + } + else + { + return aspectDefinition; + } + if (match == null) + { + return null; + } + else + { + return dictionaryService.getAspect(match); + } + } + + public static TypeDefinition matchTypeDefinition(String defaultNameSpaceUri, NamespacePrefixResolver namespacePrefixResolver, DictionaryService dictionaryService, String string) + { + QName search = QName.createQName(expandQName(defaultNameSpaceUri, namespacePrefixResolver, string)); + TypeDefinition typeDefinition = dictionaryService.getType(QName.createQName(expandQName(defaultNameSpaceUri, namespacePrefixResolver, string))); + QName match = null; + if (typeDefinition == null) + { + for (QName definition : dictionaryService.getAllTypes()) + { + if (definition.getNamespaceURI().equalsIgnoreCase(search.getNamespaceURI())) + { + if (definition.getLocalName().equalsIgnoreCase(search.getLocalName())) + { + if (match == null) + { + match = definition; + } + else + { + throw new DictionaryException("Ambiguous data datype " + string); + } + } + } + } + } + else + { + return typeDefinition; + } + if (match == null) + { + return null; + } + else + { + return dictionaryService.getType(match); + } + } + + public static DataTypeDefinition matchDataTypeDefinition(String defaultNameSpaceUri, NamespacePrefixResolver namespacePrefixResolver, DictionaryService dictionaryService, String string) + { + QName search = QName.createQName(QueryParserUtils.expandQName(defaultNameSpaceUri, namespacePrefixResolver, string)); + DataTypeDefinition dataTypeDefinition = dictionaryService.getDataType(QName.createQName(QueryParserUtils.expandQName(defaultNameSpaceUri, namespacePrefixResolver, string))); + QName match = null; + if (dataTypeDefinition == null) + { + for (QName definition : dictionaryService.getAllDataTypes()) + { + if (definition.getNamespaceURI().equalsIgnoreCase(search.getNamespaceURI())) + { + if (definition.getLocalName().equalsIgnoreCase(search.getLocalName())) + { + if (match == null) + { + match = definition; + } + else + { + throw new DictionaryException("Ambiguous data datype " + string); + } + } + } + + } + } + else + { + return dataTypeDefinition; + } + if (match == null) + { + return null; + } + else + { + return dictionaryService.getDataType(match); + } + } + + public static PropertyDefinition matchPropertyDefinition(String defaultNameSpaceUri, NamespacePrefixResolver namespacePrefixResolver, DictionaryService dictionaryService, String string) + { + QName search = QName.createQName(QueryParserUtils.expandQName(defaultNameSpaceUri, namespacePrefixResolver, string)); + PropertyDefinition propertyDefinition = dictionaryService.getProperty(QName.createQName(QueryParserUtils.expandQName(defaultNameSpaceUri, namespacePrefixResolver, string))); + QName match = null; + if (propertyDefinition == null) + { + for (QName definition : dictionaryService.getAllProperties(null)) + { + if (definition.getNamespaceURI().equalsIgnoreCase(search.getNamespaceURI())) + { + if (definition.getLocalName().equalsIgnoreCase(search.getLocalName())) + { + if (match == null) + { + match = definition; + } + else + { + throw new DictionaryException("Ambiguous data datype " + string); + } + } + } + + } + } + else + { + return propertyDefinition; + } + if (match == null) + { + return null; + } + else + { + return dictionaryService.getProperty(match); + } + } + + public static Pair extractFieldNameAndEnding(String field) + { + String propertyFieldName = null; + String ending = ""; + if (field.endsWith(FIELD_MIMETYPE_SUFFIX)) + { + propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_MIMETYPE_SUFFIX.length()); + ending = FIELD_MIMETYPE_SUFFIX; + } + else if (field.endsWith(FIELD_SIZE_SUFFIX)) + { + propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_SIZE_SUFFIX.length()); + ending = FIELD_SIZE_SUFFIX; + } + else if (field.endsWith(FIELD_LOCALE_SUFFIX)) + { + propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_LOCALE_SUFFIX.length()); + ending = FIELD_LOCALE_SUFFIX; + } + else if (field.endsWith(FIELD_ENCODING_SUFFIX)) + { + propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_ENCODING_SUFFIX.length()); + ending = FIELD_ENCODING_SUFFIX; + } + else if (field.endsWith(FIELD_CONTENT_DOC_ID_SUFFIX)) + { + propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_CONTENT_DOC_ID_SUFFIX.length()); + ending = FIELD_CONTENT_DOC_ID_SUFFIX; + } + else if (field.endsWith(FIELD_TRANSFORMATION_EXCEPTION_SUFFIX)) + { + propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_TRANSFORMATION_EXCEPTION_SUFFIX.length()); + ending = FIELD_TRANSFORMATION_EXCEPTION_SUFFIX; + } + else if (field.endsWith(FIELD_TRANSFORMATION_TIME_SUFFIX)) + { + propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_TRANSFORMATION_TIME_SUFFIX.length()); + ending = FIELD_TRANSFORMATION_TIME_SUFFIX; + } + else if (field.endsWith(FIELD_TRANSFORMATION_STATUS_SUFFIX)) + { + propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_TRANSFORMATION_STATUS_SUFFIX.length()); + ending = FIELD_TRANSFORMATION_STATUS_SUFFIX; + } + // ordering matters .__.u before .u + else if (field.endsWith(FIELD_SOLR_NOLOCALE_UNTOKENISED_SUFFIX)) + { + propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_SOLR_NOLOCALE_UNTOKENISED_SUFFIX.length()); + ending = FIELD_SOLR_NOLOCALE_UNTOKENISED_SUFFIX; + } + else if (field.endsWith(FIELD_SOLR_LOCALISED_UNTOKENISED_SUFFIX)) + { + propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_SOLR_LOCALISED_UNTOKENISED_SUFFIX.length()); + ending = FIELD_SOLR_LOCALISED_UNTOKENISED_SUFFIX; + } + else if (field.endsWith(FIELD_SOLR_NOLOCALE_TOKENISED_SUFFIX)) + { + propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0, field.length() - FIELD_SOLR_NOLOCALE_TOKENISED_SUFFIX.length()); + ending = FIELD_SOLR_NOLOCALE_TOKENISED_SUFFIX; + } + else + { + propertyFieldName = field.substring(field.startsWith("@") ? 1 : 0); + } + return new Pair<>(propertyFieldName, ending); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java new file mode 100644 index 0000000000..f929f81901 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java @@ -0,0 +1,551 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.parsers; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; + +import org.alfresco.repo.dictionary.IndexTokenisationMode; +import org.alfresco.repo.search.adaptor.lucene.LuceneFunction; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.adaptor.lucene.QueryConstants; +import org.alfresco.repo.search.impl.querymodel.FunctionArgument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.repo.search.impl.querymodel.Selector; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; + +/** + * Alfrecso function evaluation context for evaluating FTS expressions against lucene. + * + * @author andyh + */ +@SuppressWarnings("deprecation") +public class AlfrescoFunctionEvaluationContext implements FunctionEvaluationContext +{ + private static HashSet EXPOSED_FIELDS = new HashSet(); + + private NamespacePrefixResolver namespacePrefixResolver; + + private DictionaryService dictionaryService; + + private String defaultNamespace; + + static + { + EXPOSED_FIELDS.add(QueryConstants.FIELD_PATH); + EXPOSED_FIELDS.add(QueryConstants.FIELD_TEXT); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ID); + EXPOSED_FIELDS.add(QueryConstants.FIELD_SOLR4_ID); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ISROOT); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ISNODE); + EXPOSED_FIELDS.add(QueryConstants.FIELD_TX); + EXPOSED_FIELDS.add(QueryConstants.FIELD_PARENT); + EXPOSED_FIELDS.add(QueryConstants.FIELD_PRIMARYPARENT); + EXPOSED_FIELDS.add(QueryConstants.FIELD_QNAME); + EXPOSED_FIELDS.add(QueryConstants.FIELD_CLASS); + EXPOSED_FIELDS.add(QueryConstants.FIELD_TYPE); + EXPOSED_FIELDS.add(QueryConstants.FIELD_EXACTTYPE); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ASPECT); + EXPOSED_FIELDS.add(QueryConstants.FIELD_EXACTASPECT); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ALL); + EXPOSED_FIELDS.add(QueryConstants.FIELD_EXISTS); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ISUNSET); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ISNULL); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ISNOTNULL); + EXPOSED_FIELDS.add(QueryConstants.FIELD_FTSSTATUS); + EXPOSED_FIELDS.add(QueryConstants.FIELD_FTSREF); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ASSOCTYPEQNAME); + EXPOSED_FIELDS.add(QueryConstants.FIELD_PRIMARYASSOCTYPEQNAME); + EXPOSED_FIELDS.add(QueryConstants.FIELD_PRIMARYASSOCQNAME); + EXPOSED_FIELDS.add(QueryConstants.FIELD_DBID); + EXPOSED_FIELDS.add(QueryConstants.FIELD_TAG); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ACLID); + EXPOSED_FIELDS.add(QueryConstants.FIELD_OWNER); + EXPOSED_FIELDS.add(QueryConstants.FIELD_READER); + EXPOSED_FIELDS.add(QueryConstants.FIELD_AUTHORITY); + EXPOSED_FIELDS.add(QueryConstants.FIELD_OWNERSET); + EXPOSED_FIELDS.add(QueryConstants.FIELD_READERSET); + EXPOSED_FIELDS.add(QueryConstants.FIELD_AUTHORITYSET); + EXPOSED_FIELDS.add(QueryConstants.FIELD_DENIED); + EXPOSED_FIELDS.add(QueryConstants.FIELD_DENYSET); + EXPOSED_FIELDS.add(QueryConstants.FIELD_TXID); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ACLTXID); + EXPOSED_FIELDS.add(QueryConstants.FIELD_TXCOMMITTIME); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ACLTXCOMMITTIME); + EXPOSED_FIELDS.add(QueryConstants.FIELD_INACLTXID); + EXPOSED_FIELDS.add(QueryConstants.FIELD_INTXID); + EXPOSED_FIELDS.add(QueryConstants.FIELD_TENANT); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ANCESTOR); + EXPOSED_FIELDS.add(QueryConstants.FIELD_EXCEPTION_MESSAGE); + EXPOSED_FIELDS.add(QueryConstants.FIELD_EXCEPTION_STACK); + EXPOSED_FIELDS.add(QueryConstants.FIELD_LID); + EXPOSED_FIELDS.add(QueryConstants.FIELD_PARENT_ASSOC_CRC); + EXPOSED_FIELDS.add(QueryConstants.FIELD_SITE); + EXPOSED_FIELDS.add(QueryConstants.FIELD_TAG); + EXPOSED_FIELDS.add(QueryConstants.FIELD_PNAME); + EXPOSED_FIELDS.add(QueryConstants.FIELD_NPATH); + EXPOSED_FIELDS.add(QueryConstants.FIELD_ANAME); + EXPOSED_FIELDS.add(QueryConstants.FIELD_APATH); + EXPOSED_FIELDS.add(QueryConstants.FIELD_DOC_TYPE); + EXPOSED_FIELDS.add(QueryConstants.FIELD_PROPERTIES); + EXPOSED_FIELDS.add(QueryConstants.FIELD_NULLPROPERTIES); + EXPOSED_FIELDS.add(QueryConstants.FIELD_FINGERPRINT); + } + + /** + * @param namespacePrefixResolver NamespacePrefixResolver + * @param dictionaryService DictionaryService + * @param defaultNamespace String + */ + public AlfrescoFunctionEvaluationContext(NamespacePrefixResolver namespacePrefixResolver, DictionaryService dictionaryService, String defaultNamespace) + { + this.namespacePrefixResolver = namespacePrefixResolver; + this.dictionaryService = dictionaryService; + this.defaultNamespace = defaultNamespace; + } + + public Q buildLuceneEquality(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + throw new UnsupportedOperationException(); + } + + public Q buildLuceneExists(LuceneQueryParserAdaptor lqpa, String propertyName, Boolean not) throws E + { + throw new UnsupportedOperationException(); + } + + public Q buildLuceneGreaterThan(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + throw new UnsupportedOperationException(); + } + + public Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) + throws E + { + throw new UnsupportedOperationException(); + } + + public Q buildLuceneIn(LuceneQueryParserAdaptor lqpa, String propertyName, Collection values, Boolean not, PredicateMode mode) throws E + { + throw new UnsupportedOperationException(); + } + + public Q buildLuceneInequality(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + throw new UnsupportedOperationException(); + } + + public Q buildLuceneLessThan(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E + { + throw new UnsupportedOperationException(); + } + + public Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) + throws E + { + throw new UnsupportedOperationException(); + } + + public Q buildLuceneLike(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, Boolean not) throws E + { + throw new UnsupportedOperationException(); + } + + public String getLuceneSortField(LuceneQueryParserAdaptor lqpa, String propertyName) throws E + { + // Score is special + if (propertyName.equalsIgnoreCase("Score")) + { + return "Score"; + } + String field = getLuceneFieldName(propertyName); + // need to find the real field to use + if (field.startsWith(QueryConstants.PROPERTY_FIELD_PREFIX)) + { + PropertyDefinition propertyDef = dictionaryService.getProperty(QName.createQName(field.substring(1))); + + // Handle .size and .mimetype + if(propertyDef == null) + { + if(field.endsWith(QueryConstants.FIELD_SIZE_SUFFIX)) + { + propertyDef = dictionaryService.getProperty(QName.createQName(field.substring(1, field.length()-QueryConstants.FIELD_SIZE_SUFFIX.length()))); + if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) + { + throw new FTSQueryException("Order for "+QueryConstants.FIELD_SIZE_SUFFIX+" only supported on content properties"); + } + else + { + return field; + } + } + else if (field.endsWith(QueryConstants.FIELD_MIMETYPE_SUFFIX)) + { + propertyDef = dictionaryService.getProperty(QName.createQName(field.substring(1, field.length()-QueryConstants.FIELD_MIMETYPE_SUFFIX.length()))); + if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) + { + throw new FTSQueryException("Order for .mimetype only supported on content properties"); + } + else + { + return field; + } + } + else + { + return field; + } + } + else + { + if (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) + { + throw new FTSQueryException("Order on content properties is not curently supported"); + } + else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT)) + { + if(propertyDef.getIndexTokenisationMode() == IndexTokenisationMode.FALSE) + { + return field; + } + + String noLocalField = field+".no_locale"; + if(lqpa.sortFieldExists(noLocalField)) + { + return noLocalField; + } + field = findSortField(lqpa, field); + } + else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT)) + { + field = findSortField(lqpa, field); + + } + else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME)) + { + field = lqpa.getDatetimeSortField(field, propertyDef); + } + } + } + return field; + } + + /** + * @param lqpa LuceneQueryParserAdaptor + * @param field String + * @return ... extends Throwable + * @throws E + */ + private String findSortField(LuceneQueryParserAdaptor lqpa, String field) throws E + { + return lqpa.getSortField(field); + } + + public Map getNodeRefs() + { + throw new UnsupportedOperationException(); + } + + public NodeService getNodeService() + { + throw new UnsupportedOperationException(); + } + + public Serializable getProperty(NodeRef nodeRef, String propertyName) + { + throw new UnsupportedOperationException(); + } + + public Float getScore() + { + throw new UnsupportedOperationException(); + } + + public Map getScores() + { + throw new UnsupportedOperationException(); + } + + public boolean isObjectId(String propertyName) + { + return false; + } + + public boolean isOrderable(String fieldName) + { + return true; + } + + public boolean isQueryable(String fieldName) + { + return true; + } + + public String getLuceneFieldName(String propertyName) + { + if (propertyName.startsWith(QueryConstants.PROPERTY_FIELD_PREFIX)) + { + // Leave it to the query parser to expand + return propertyName; + } + + if (propertyName.startsWith("{")) + { + QName fullQName = QName.createQName(propertyName); + QName propertyQName = stripSuffixes(fullQName); + if (dictionaryService.getProperty(propertyQName) != null) + { + return QueryConstants.PROPERTY_FIELD_PREFIX + fullQName.toString(); + } + else if(dictionaryService.getDataType(fullQName) != null) + { + return fullQName.toString(); + } + else + { + throw new FTSQueryException("Unknown property: " + fullQName.toString()); + } + } + + int index = propertyName.indexOf(':'); + if (index != -1) + { + // Try as a property, if invalid pass through + QName fullQName = QName.createQName(propertyName, namespacePrefixResolver); + QName propertyQName = stripSuffixes(fullQName); + if (dictionaryService.getProperty(propertyQName) != null) + { + return QueryConstants.PROPERTY_FIELD_PREFIX + fullQName.toString(); + } + else if(dictionaryService.getDataType(fullQName) != null) + { + return fullQName.toString(); + } + else + { + throw new FTSQueryException("Unknown property: " + fullQName.toString()); + } + } + + if (!EXPOSED_FIELDS.contains(propertyName)) + { + index = propertyName.indexOf('_'); + if (index != -1) + { + // Try as a property, if invalid pass through + QName fullQName = QName.createQName(propertyName.substring(0, index), propertyName.substring(index + 1), namespacePrefixResolver); + QName propertyQName = stripSuffixes(fullQName); + if (dictionaryService.getProperty(propertyQName) != null) + { + return QueryConstants.PROPERTY_FIELD_PREFIX + fullQName.toString(); + } + else + { + throw new FTSQueryException("Unknown property: " + fullQName.toString()); + } + } + } + + if (EXPOSED_FIELDS.contains(propertyName)) + { + return propertyName; + } + + QName fullQName = QName.createQName(defaultNamespace, propertyName); + QName propertyQName = stripSuffixes(fullQName); + if (dictionaryService.getProperty(propertyQName) != null) + { + return QueryConstants.PROPERTY_FIELD_PREFIX + fullQName.toString(); + } + else if(dictionaryService.getDataType(fullQName) != null) + { + return fullQName.toString(); + } + else + { + if(propertyName.equalsIgnoreCase("Score")) + { + return propertyName.toLowerCase(); + } + + throw new FTSQueryException("Unknown property: " + fullQName.toString()); + } + + } + + public QName stripSuffixes(QName qname) + { + String field = qname.toString(); + if(field.endsWith(QueryConstants.FIELD_SIZE_SUFFIX)) + { + QName propertyField = QName.createQName(field.substring(0, field.length()-QueryConstants.FIELD_SIZE_SUFFIX.length())); + PropertyDefinition propertyDef = dictionaryService.getProperty(propertyField); + if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) + { + throw new FTSQueryException(QueryConstants.FIELD_SIZE_SUFFIX+" only supported on content properties"); + } + else + { + return propertyField; + } + } + else if(field.endsWith(QueryConstants.FIELD_LOCALE_SUFFIX)) + { + QName propertyField = QName.createQName(field.substring(0, field.length()-QueryConstants.FIELD_LOCALE_SUFFIX.length())); + PropertyDefinition propertyDef = dictionaryService.getProperty(propertyField); + if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) + { + throw new FTSQueryException(QueryConstants.FIELD_LOCALE_SUFFIX+" only supported on content properties"); + } + else + { + return propertyField; + } + } + else if(field.endsWith(QueryConstants.FIELD_MIMETYPE_SUFFIX)) + { + QName propertyField = QName.createQName(field.substring(0, field.length()-QueryConstants.FIELD_MIMETYPE_SUFFIX.length())); + PropertyDefinition propertyDef = dictionaryService.getProperty(propertyField); + if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) + { + throw new FTSQueryException(QueryConstants.FIELD_MIMETYPE_SUFFIX+" only supported on content properties"); + } + else + { + return propertyField; + } + } + else if(field.endsWith(QueryConstants.FIELD_ENCODING_SUFFIX)) + { + QName propertyField = QName.createQName(field.substring(0, field.length()-QueryConstants.FIELD_ENCODING_SUFFIX.length())); + PropertyDefinition propertyDef = dictionaryService.getProperty(propertyField); + if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) + { + throw new FTSQueryException(QueryConstants.FIELD_ENCODING_SUFFIX+" only supported on content properties"); + } + else + { + return propertyField; + } + } + else if(field.endsWith(QueryConstants.FIELD_TRANSFORMATION_EXCEPTION_SUFFIX)) + { + QName propertyField = QName.createQName(field.substring(0, field.length()-QueryConstants.FIELD_TRANSFORMATION_EXCEPTION_SUFFIX.length())); + PropertyDefinition propertyDef = dictionaryService.getProperty(propertyField); + if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) + { + throw new FTSQueryException(QueryConstants.FIELD_TRANSFORMATION_EXCEPTION_SUFFIX+" only supported on content properties"); + } + else + { + return propertyField; + } + } + else if(field.endsWith(QueryConstants.FIELD_TRANSFORMATION_STATUS_SUFFIX)) + { + QName propertyField = QName.createQName(field.substring(0, field.length()-QueryConstants.FIELD_TRANSFORMATION_STATUS_SUFFIX.length())); + PropertyDefinition propertyDef = dictionaryService.getProperty(propertyField); + if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) + { + throw new FTSQueryException(QueryConstants.FIELD_TRANSFORMATION_STATUS_SUFFIX+" only supported on content properties"); + } + else + { + return propertyField; + } + } + else if(field.endsWith(QueryConstants.FIELD_TRANSFORMATION_TIME_SUFFIX)) + { + QName propertyField = QName.createQName(field.substring(0, field.length()-QueryConstants.FIELD_TRANSFORMATION_TIME_SUFFIX.length())); + PropertyDefinition propertyDef = dictionaryService.getProperty(propertyField); + if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) + { + throw new FTSQueryException(QueryConstants.FIELD_TRANSFORMATION_TIME_SUFFIX+" only supported on content properties"); + } + else + { + return propertyField; + } + } + else + { + return qname; + } + } + + public LuceneFunction getLuceneFunction(FunctionArgument functionArgument) + { + throw new UnsupportedOperationException(); + } + + /* + * (non-Javadoc) + * @see + * org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#checkFieldApplies(org.alfresco.service.namespace + * .QName, java.lang.String) + */ + public void checkFieldApplies(Selector selector, String propertyName) + { + throw new UnsupportedOperationException(); + } + + /* + * (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#isMultiValued(java.lang.String) + */ + public boolean isMultiValued(String propertyName) + { + throw new UnsupportedOperationException(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#getAlfrescoQName(org.alfresco.service.namespace.QName) + */ + @Override + public String getAlfrescoPropertyName(String propertyName) + { + return propertyName; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext#getAlfrescoTypeName(java.lang.String) + */ + @Override + public String getAlfrescoTypeName(String typeName) + { + return typeName; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS.g b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS.g new file mode 100644 index 0000000000..626d6fbf41 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS.g @@ -0,0 +1,1670 @@ +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +/* + * Parser for the CMIS query language + * + * The semantics of multivalued properties are ignored for the initial parse of the language. + * They are applied in a second pass, when we have enough information to determine the column type. + */ + +grammar CMIS; + +options +{ + output = AST; +} + +tokens +{ + QUERY; + ALL_COLUMNS; + COLUMN; + COLUMNS; + COLUMN_REF; + QUALIFIER; + FUNCTION; + SOURCE; + TABLE; + TABLE_REF; + PARAMETER; + CONJUNCTION; + DISJUNCTION; + NEGATION; + PRED_COMPARISON; + PRED_IN; + PRED_EXISTS; + PRED_LIKE; + PRED_FTS; + LIST; + PRED_CHILD; + PRED_DESCENDANT; + SORT_SPECIFICATION; + NUMERIC_LITERAL; + STRING_LITERAL; + DATETIME_LITERAL; + BOOLEAN_LITERAL; + SINGLE_VALUED_PROPERTY; +} + +@lexer::header +{ + package org.alfresco.repo.search.impl.parsers; + import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; +} + +@header +{ + package org.alfresco.repo.search.impl.parsers; + import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; +} +/* + * Instance methods and properties for the parser. + * Realisations of the parser should over-ride these as required + */ + + +@members +{ + private Stack paraphrases = new Stack(); + + private boolean strict = false; + + /** + * CMIS strict + */ + public boolean strict() + { + return strict; + } + + public void setStrict(boolean strict) + { + this.strict = strict; + } + + protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException + { + throw new MismatchedTokenException(ttype, input); + } + + public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException + { + throw e; + } + + public String getErrorMessage(RecognitionException e, String[] tokenNames) + { + List stack = getRuleInvocationStack(e, this.getClass().getName()); + String msg = e.getMessage(); + if ( e instanceof UnwantedTokenException ) + { + UnwantedTokenException ute = (UnwantedTokenException)e; + String tokenName=""; + if ( ute.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[ute.expecting]; + } + msg = "extraneous input " + getTokenErrorDisplay(ute.getUnexpectedToken()) + + " expecting "+tokenName; + } + else if ( e instanceof MissingTokenException ) + { + MissingTokenException mte = (MissingTokenException)e; + String tokenName=""; + if ( mte.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mte.expecting]; + } + msg = "missing " + tokenName+" at " + getTokenErrorDisplay(e.token) + + " (" + getLongTokenErrorDisplay(e.token) +")"; + } + else if ( e instanceof MismatchedTokenException ) + { + MismatchedTokenException mte = (MismatchedTokenException)e; + String tokenName=""; + if ( mte.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mte.expecting]; + } + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting " + tokenName +" (" + getLongTokenErrorDisplay(e.token) + ")"; + } + else if ( e instanceof MismatchedTreeNodeException ) + { + MismatchedTreeNodeException mtne = (MismatchedTreeNodeException)e; + String tokenName=""; + if ( mtne.expecting==Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mtne.expecting]; + } + msg = "mismatched tree node: " + mtne.node + " expecting " + tokenName; + } + else if ( e instanceof NoViableAltException ) + { + NoViableAltException nvae = (NoViableAltException)e; + msg = "no viable alternative at input " + getTokenErrorDisplay(e.token) + + "\n\t (decision=" + nvae.decisionNumber + + " state " + nvae.stateNumber + ")" + + " decision=<<" + nvae.grammarDecisionDescription + ">>"; + } + else if ( e instanceof EarlyExitException ) + { + //EarlyExitException eee = (EarlyExitException)e; + // for development, can add "(decision="+eee.decisionNumber+")" + msg = "required (...)+ loop did not match anything at input " + getTokenErrorDisplay(e.token); + } + else if ( e instanceof MismatchedSetException ) + { + MismatchedSetException mse = (MismatchedSetException)e; + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting set " + mse.expecting; + } + else if ( e instanceof MismatchedNotSetException ) + { + MismatchedNotSetException mse = (MismatchedNotSetException)e; + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting set " + mse.expecting; + } + else if ( e instanceof FailedPredicateException ) + { + FailedPredicateException fpe = (FailedPredicateException)e; + msg = "rule " + fpe.ruleName + " failed predicate: {" + fpe.predicateText + "}?"; + } + + if(paraphrases.size() > 0) + { + String paraphrase = (String)paraphrases.peek(); + msg = msg+" "+paraphrase; + } + return msg +"\n\t"+stack; + } + + public String getLongTokenErrorDisplay(Token t) + { + return t.toString(); + } + + + public String getErrorString(RecognitionException e) + { + String hdr = getErrorHeader(e); + String msg = getErrorMessage(e, this.getTokenNames()); + return hdr+" "+msg; + } +} + +@rulecatch +{ + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } +} + +@lexer::members +{ + public Token nextToken() { + while (true) + { + state.token = null; + state.channel = Token.DEFAULT_CHANNEL; + state.tokenStartCharIndex = input.index(); + state.tokenStartCharPositionInLine = input.getCharPositionInLine(); + state.tokenStartLine = input.getLine(); + state.text = null; + if ( input.LA(1)==CharStream.EOF ) + { + return getEOFToken(); + } + try + { + mTokens(); + if ( state.token==null ) + { + emit(); + } + else if ( state.token==Token.SKIP_TOKEN ) + { + continue; + } + return state.token; + } + catch (RecognitionException re) + { + throw new CmisInvalidArgumentException(getErrorString(re), re); + } + } + } + + public String getErrorString(RecognitionException e) + { + String hdr = getErrorHeader(e); + String msg = getErrorMessage(e, this.getTokenNames()); + return hdr+" "+msg; + } +} + +/** + * This is mostly a direct take fom the CMIS spec. + * The only significant chnanges are to remove left recursion which is not supported in antlr + * + * The top level rule for the parser + */ +query +@init +{ + paraphrases.push("in query"); +} +@after +{ + paraphrases.pop(); +} + : + SELECT selectList fromClause whereClause? orderByClause? EOF + -> + ^(QUERY selectList fromClause whereClause? orderByClause?) + ; + +selectList +@init +{ + paraphrases.push("in select list"); +} +@after +{ + paraphrases.pop(); +} + : + STAR + -> + ^(ALL_COLUMNS) + | selectSubList (COMMA selectSubList)* + -> + ^(COLUMNS selectSubList+) + ; + +selectSubList + : + valueExpression (AS? columnName)? + -> + ^(COLUMN valueExpression columnName?) + | qualifier DOTSTAR + -> + ^(ALL_COLUMNS qualifier) + ; + +valueExpression +@init +{ + paraphrases.push("in value expression"); +} +@after +{ + paraphrases.pop(); +} + : + columnReference + -> columnReference + | valueFunction + -> valueFunction + ; + +columnReference +@init +{ + paraphrases.push("in column reference"); +} +@after +{ + paraphrases.pop(); +} + : + (qualifier DOT)? columnName + -> + ^(COLUMN_REF columnName qualifier?) + ; + +valueFunction +@init +{ + paraphrases.push("in function"); +} +@after +{ + paraphrases.pop(); +} + : + cmisFunctionName=cmisFunction LPAREN functionArgument* RPAREN + -> + ^(FUNCTION $cmisFunctionName LPAREN functionArgument* RPAREN) + | {strict == false}?=> functionName=keyWordOrId LPAREN functionArgument* RPAREN + -> + ^(FUNCTION $functionName LPAREN functionArgument* RPAREN) + ; + +functionArgument + : + qualifier DOT columnName + -> + ^(COLUMN_REF columnName qualifier) + | identifier + | literalOrParameterName + ; + +qualifier + : + (tableName) => tableName + -> tableName + | correlationName + -> correlationName + ; + +fromClause +@init +{ + paraphrases.push("in fromClause"); +} +@after +{ + paraphrases.pop(); +} + : + FROM tableReference + -> tableReference + ; + +tableReference +@init +{ + paraphrases.push("in tableReference"); +} +@after +{ + paraphrases.pop(); +} + : + singleTable joinedTable* + -> + ^(SOURCE singleTable joinedTable*) + ; +/* + * Created to avoid left recursion between tableReference and joinedTable. + */ + + +singleTable +@init +{ + paraphrases.push("in singleTable"); +} +@after +{ + paraphrases.pop(); +} + : + simpleTable + -> simpleTable + | complexTable + -> + ^(TABLE complexTable) + ; + +simpleTable +@init +{ + paraphrases.push("in simpleTable"); +} +@after +{ + paraphrases.pop(); +} + : + tableName (AS? correlationName)? + -> + ^(TABLE_REF tableName correlationName?) + ; + +joinedTable +@init +{ + paraphrases.push("in joinedTable"); +} +@after +{ + paraphrases.pop(); +} + : + joinType? JOIN tableReference joinSpecification + -> + ^(JOIN tableReference joinType? joinSpecification) + ; + +complexTable +@init +{ + paraphrases.push("in complexTable"); +} +@after +{ + paraphrases.pop(); +} + : + (LPAREN singleTable joinedTable+ RPAREN) => LPAREN singleTable joinedTable+ RPAREN + -> + ^(SOURCE singleTable joinedTable+) + | LPAREN complexTable RPAREN + -> complexTable + ; + +joinType + : + INNER + -> INNER + | LEFT OUTER? + -> LEFT + ; + +joinSpecification +@init +{ + paraphrases.push("in join condition"); +} +@after +{ + paraphrases.pop(); +} + : + ON lhs=columnReference EQUALS rhs=columnReference + -> + ^(ON $lhs EQUALS $rhs) + ; +/* + * Broken out the left recursion from the spec + */ + + +whereClause +@init +{ + paraphrases.push("in where"); +} +@after +{ + paraphrases.pop(); +} + : + WHERE searchOrCondition + -> searchOrCondition + ; + +/** + * Broken left recursion. + */ +searchOrCondition + : + searchAndCondition (OR searchAndCondition)* + -> + ^(DISJUNCTION searchAndCondition+) + ; + +/** + * Broken left recursion. + */ +searchAndCondition + : + searchNotCondition (AND searchNotCondition)* + -> + ^(CONJUNCTION searchNotCondition+) + ; + +searchNotCondition + : + NOT searchTest + -> + ^(NEGATION searchTest) + | searchTest + -> searchTest + ; + +searchTest + : + predicate + -> predicate + | LPAREN searchOrCondition RPAREN + -> searchOrCondition + ; + +predicate + : + comparisonPredicate + | inPredicate + | likePredicate + | nullPredicate + | quantifiedComparisonPredicate + | quantifiedInPredicate + | textSearchPredicate + | folderPredicate + ; + +comparisonPredicate + : + valueExpression compOp literalOrParameterName + -> + ^(PRED_COMPARISON SINGLE_VALUED_PROPERTY valueExpression compOp literalOrParameterName) + ; + +compOp + : + EQUALS + | NOTEQUALS + | LESSTHAN + | GREATERTHAN + | LESSTHANOREQUALS + | GREATERTHANOREQUALS + ; + +literalOrParameterName + : + literal + | {strict == false}?=> parameterName + ; + +literal + : + signedNumericLiteral + | characterStringLiteral + | booleanLiteral + | datetimeLiteral + ; + +inPredicate + : + columnReference NOT? IN LPAREN inValueList RPAREN + -> + ^(PRED_IN SINGLE_VALUED_PROPERTY columnReference inValueList NOT?) + ; + +inValueList + : + literalOrParameterName (COMMA literalOrParameterName)* + -> + ^(LIST literalOrParameterName+) + ; + +likePredicate + : + columnReference NOT? LIKE characterStringLiteral + -> + ^(PRED_LIKE columnReference characterStringLiteral NOT?) + ; + +nullPredicate + : + columnReference IS NULL + -> + ^(PRED_EXISTS columnReference NOT) + | columnReference IS NOT NULL + -> + ^(PRED_EXISTS columnReference) + ; + +quantifiedComparisonPredicate + : + literalOrParameterName compOp ANY columnReference + -> + ^(PRED_COMPARISON ANY literalOrParameterName compOp columnReference) + ; + +quantifiedInPredicate + : + ANY columnReference NOT? IN LPAREN inValueList RPAREN + -> + ^(PRED_IN ANY columnReference inValueList NOT?) + ; + +textSearchPredicate + : + CONTAINS LPAREN (qualifier COMMA)? textSearchExpression RPAREN + -> + ^(PRED_FTS textSearchExpression qualifier?) + ; + +folderPredicate + : + IN_FOLDER folderPredicateArgs + -> + ^(PRED_CHILD folderPredicateArgs) + | IN_TREE folderPredicateArgs + -> + ^(PRED_DESCENDANT folderPredicateArgs) + ; + +folderPredicateArgs + : + LPAREN (qualifier COMMA)? folderId RPAREN + -> folderId qualifier? + ; + +orderByClause +@init +{ + paraphrases.push("in order by"); +} +@after +{ + paraphrases.pop(); +} + : + ORDER BY sortSpecification (COMMA sortSpecification)* + -> + ^(ORDER sortSpecification+) + ; + +sortSpecification + : + columnReference + -> + ^(SORT_SPECIFICATION columnReference ASC) + | columnReference + ( + by=ASC + | by=DESC + ) + -> + ^(SORT_SPECIFICATION columnReference $by) + ; + +correlationName + : + identifier + ; +/* + * Parse time validation of the table name + * TODO wire up the look a head + */ + + +tableName + : + identifier + -> identifier + ; + +columnName + : + identifier + -> identifier + ; + +parameterName + : + COLON identifier + -> + ^(PARAMETER identifier) + ; + +folderId + : + characterStringLiteral + -> characterStringLiteral + ; + +textSearchExpression + : + QUOTED_STRING + ; + +identifier + : + ID + -> ID + | {strict == false}?=> DOUBLE_QUOTE keyWordOrId DOUBLE_QUOTE + -> + ^(keyWordOrId) + ; + +signedNumericLiteral + : + FLOATING_POINT_LITERAL + -> + ^(NUMERIC_LITERAL FLOATING_POINT_LITERAL) + | integerLiteral + -> integerLiteral + ; + +integerLiteral + : + DECIMAL_INTEGER_LITERAL + -> + ^(NUMERIC_LITERAL DECIMAL_INTEGER_LITERAL) + ; + +booleanLiteral + : + TRUE + -> + ^(BOOLEAN_LITERAL TRUE) + | FALSE + -> + ^(BOOLEAN_LITERAL FALSE) + ; + +datetimeLiteral + : + TIMESTAMP QUOTED_STRING + -> + ^(DATETIME_LITERAL QUOTED_STRING) + ; + +characterStringLiteral + : + QUOTED_STRING + -> + ^(STRING_LITERAL QUOTED_STRING) + ; + +keyWord + : + SELECT + | AS + | FROM + | JOIN + | INNER + | LEFT + | OUTER + | ON + | WHERE + | OR + | AND + | NOT + | IN + | LIKE + | IS + | NULL + | ANY + | CONTAINS + | IN_FOLDER + | IN_TREE + | ORDER + | BY + | ASC + | DESC + | TIMESTAMP + | TRUE + | FALSE + | cmisFunction + ; + +cmisFunction + : + SCORE + -> SCORE + ; + +keyWordOrId + : + keyWord + -> keyWord + | ID + -> ID + ; +/* + * LEXER + */ +/* + * Quoted strings take precedence + */ + + + +QUOTED_STRING + : + '\'' + ( + ~('\'' | '\\') + | '\\' . + )* + '\'' + ; + +SELECT + : + ( + 'S' + | 's' + ) + ( + 'E' + | 'e' + ) + ( + 'L' + | 'l' + ) + ( + 'E' + | 'e' + ) + ( + 'C' + | 'c' + ) + ( + 'T' + | 't' + ) + ; + +AS + : + ( + 'A' + | 'a' + ) + ( + 'S' + | 's' + ) + ; + +FROM + : + ( + 'F' + | 'f' + ) + ( + 'R' + | 'r' + ) + ( + 'O' + | 'o' + ) + ( + 'M' + | 'm' + ) + ; + +JOIN + : + ( + 'J' + | 'j' + ) + ( + 'O' + | 'o' + ) + ( + 'I' + | 'i' + ) + ( + 'N' + | 'n' + ) + ; + +INNER + : + ( + 'I' + | 'i' + ) + ( + 'N' + | 'n' + ) + ( + 'N' + | 'n' + ) + ( + 'E' + | 'e' + ) + ( + 'R' + | 'r' + ) + ; + +LEFT + : + ( + 'L' + | 'l' + ) + ( + 'E' + | 'e' + ) + ( + 'F' + | 'f' + ) + ( + 'T' + | 't' + ) + ; + +OUTER + : + ( + 'O' + | 'o' + ) + ( + 'U' + | 'u' + ) + ( + 'T' + | 't' + ) + ( + 'E' + | 'e' + ) + ( + 'R' + | 'r' + ) + ; + +ON + : + ( + 'O' + | 'o' + ) + ( + 'N' + | 'n' + ) + ; + +WHERE + : + ( + 'W' + | 'w' + ) + ( + 'H' + | 'h' + ) + ( + 'E' + | 'e' + ) + ( + 'R' + | 'r' + ) + ( + 'E' + | 'e' + ) + ; + +OR + : + ( + 'O' + | 'o' + ) + ( + 'R' + | 'r' + ) + ; + +AND + : + ( + 'A' + | 'a' + ) + ( + 'N' + | 'n' + ) + ( + 'D' + | 'd' + ) + ; + +NOT + : + ( + 'N' + | 'n' + ) + ( + 'O' + | 'o' + ) + ( + 'T' + | 't' + ) + ; + +IN + : + ( + 'I' + | 'i' + ) + ( + 'N' + | 'n' + ) + ; + +LIKE + : + ( + 'L' + | 'l' + ) + ( + 'I' + | 'i' + ) + ( + 'K' + | 'k' + ) + ( + 'E' + | 'e' + ) + ; + +IS + : + ( + 'I' + | 'i' + ) + ( + 'S' + | 's' + ) + ; + +NULL + : + ( + 'N' + | 'n' + ) + ( + 'U' + | 'u' + ) + ( + 'L' + | 'l' + ) + ( + 'L' + | 'l' + ) + ; + +ANY + : + ( + 'A' + | 'a' + ) + ( + 'N' + | 'n' + ) + ( + 'Y' + | 'y' + ) + ; + +CONTAINS + : + ( + 'C' + | 'c' + ) + ( + 'O' + | 'o' + ) + ( + 'N' + | 'n' + ) + ( + 'T' + | 't' + ) + ( + 'A' + | 'a' + ) + ( + 'I' + | 'i' + ) + ( + 'N' + | 'n' + ) + ( + 'S' + | 's' + ) + ; + +IN_FOLDER + : + ( + 'I' + | 'i' + ) + ( + 'N' + | 'n' + ) + '_' + ( + 'F' + | 'f' + ) + ( + 'O' + | 'o' + ) + ( + 'L' + | 'l' + ) + ( + 'D' + | 'd' + ) + ( + 'E' + | 'e' + ) + ( + 'R' + | 'r' + ) + ; + +IN_TREE + : + ( + 'I' + | 'i' + ) + ( + 'N' + | 'n' + ) + '_' + ( + 'T' + | 't' + ) + ( + 'R' + | 'r' + ) + ( + 'E' + | 'e' + ) + ( + 'E' + | 'e' + ) + ; + +ORDER + : + ( + 'O' + | 'o' + ) + ( + 'R' + | 'r' + ) + ( + 'D' + | 'd' + ) + ( + 'E' + | 'e' + ) + ( + 'R' + | 'r' + ) + ; + +BY + : + ( + 'B' + | 'b' + ) + ( + 'Y' + | 'y' + ) + ; + +ASC + : + ( + 'A' + | 'a' + ) + ( + 'S' + | 's' + ) + ( + 'C' + | 'c' + ) + ; + +DESC + : + ( + 'D' + | 'd' + ) + ( + 'E' + | 'e' + ) + ( + 'S' + | 's' + ) + ( + 'C' + | 'c' + ) + ; + +TIMESTAMP + : + ( + 'T' + | 't' + ) + ( + 'I' + | 'i' + ) + ( + 'M' + | 'm' + ) + ( + 'E' + | 'e' + ) + ( + 'S' + | 's' + ) + ( + 'T' + | 't' + ) + ( + 'A' + | 'a' + ) + ( + 'M' + | 'm' + ) + ( + 'P' + | 'p' + ) + ; + +TRUE + : + ( + 'T' + | 't' + ) + ( + 'R' + | 'r' + ) + ( + 'U' + | 'u' + ) + ( + 'E' + | 'e' + ) + ; + +FALSE + : + ( + 'F' + | 'f' + ) + ( + 'A' + | 'a' + ) + ( + 'L' + | 'l' + ) + ( + 'S' + | 's' + ) + ( + 'E' + | 'e' + ) + ; + +SCORE + : + ( + 'S' + | 's' + ) + ( + 'C' + | 'c' + ) + ( + 'O' + | 'o' + ) + ( + 'R' + | 'r' + ) + ( + 'E' + | 'e' + ) + ; + +LPAREN + : + '(' + ; + +RPAREN + : + ')' + ; + +STAR + : + '*' + ; + +COMMA + : + ',' + ; + +DOTSTAR + : + '.*' + ; + +DOT + : + '.' + ; + +DOTDOT + : + '..' + ; + +EQUALS + : + '=' + ; + +TILDA + : + '~' + ; + +NOTEQUALS + : + '<>' + ; + +GREATERTHAN + : + '>' + ; + +LESSTHAN + : + '<' + ; + +GREATERTHANOREQUALS + : + '>=' + ; + +LESSTHANOREQUALS + : + '<=' + ; + +COLON + : + ':' + ; + +DOUBLE_QUOTE + : + '"' + ; +/* + * Decimal adapted from the Java spec + */ + + +DECIMAL_INTEGER_LITERAL + : + ( + PLUS + | MINUS + )? + DECIMAL_NUMERAL + ; +/* + * Floating point adapted from the Java spec + */ + + +FLOATING_POINT_LITERAL + : + ( + PLUS + | MINUS + )? + DIGIT+ DOT DIGIT* EXPONENT? + | + ( + PLUS + | MINUS + )? + DOT DIGIT+ EXPONENT? + | + ( + PLUS + | MINUS + )? + DIGIT+ EXPONENT + ; + +/** + * We should support _x????_ encoding for invalid sql characters + */ +ID + : + ( + 'a'..'z' + | 'A'..'Z' + | '_' + ) + ( + 'a'..'z' + | 'A'..'Z' + | '0'..'9' + | '_' + | ':' + | '$' + | '#' + )* + ; + +WS + : + ( + ' ' + | '\t' + | '\r' + | '\n' + )+ + { $channel = HIDDEN; } + ; + +/** + * Fragments for decimal + */ +fragment +DECIMAL_NUMERAL + : + ZERO_DIGIT + | NON_ZERO_DIGIT DIGIT* + ; + +fragment +DIGIT + : + ZERO_DIGIT + | NON_ZERO_DIGIT + ; + +fragment +ZERO_DIGIT + : + '0' + ; + +fragment +NON_ZERO_DIGIT + : + '1'..'9' + ; + +fragment +PLUS + : + '+' + ; + +fragment +MINUS + : + '-' + ; + +fragment +E + : + ( + 'e' + | 'E' + ) + ; +/* + * Fragments for floating point + */ + + +fragment +EXPONENT + : + E SIGNED_INTEGER + ; + +fragment +SIGNED_INTEGER + : + ( + PLUS + | MINUS + )? + DIGIT+ + ; diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS.tokens b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS.tokens new file mode 100644 index 0000000000..4dd787013e --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS.tokens @@ -0,0 +1,86 @@ +ALL_COLUMNS=4 +AND=5 +ANY=6 +AS=7 +ASC=8 +BOOLEAN_LITERAL=9 +BY=10 +COLON=11 +COLUMN=12 +COLUMNS=13 +COLUMN_REF=14 +COMMA=15 +CONJUNCTION=16 +CONTAINS=17 +DATETIME_LITERAL=18 +DECIMAL_INTEGER_LITERAL=19 +DECIMAL_NUMERAL=20 +DESC=21 +DIGIT=22 +DISJUNCTION=23 +DOT=24 +DOTDOT=25 +DOTSTAR=26 +DOUBLE_QUOTE=27 +E=28 +EQUALS=29 +EXPONENT=30 +FALSE=31 +FLOATING_POINT_LITERAL=32 +FROM=33 +FUNCTION=34 +GREATERTHAN=35 +GREATERTHANOREQUALS=36 +ID=37 +IN=38 +INNER=39 +IN_FOLDER=40 +IN_TREE=41 +IS=42 +JOIN=43 +LEFT=44 +LESSTHAN=45 +LESSTHANOREQUALS=46 +LIKE=47 +LIST=48 +LPAREN=49 +MINUS=50 +NEGATION=51 +NON_ZERO_DIGIT=52 +NOT=53 +NOTEQUALS=54 +NULL=55 +NUMERIC_LITERAL=56 +ON=57 +OR=58 +ORDER=59 +OUTER=60 +PARAMETER=61 +PLUS=62 +PRED_CHILD=63 +PRED_COMPARISON=64 +PRED_DESCENDANT=65 +PRED_EXISTS=66 +PRED_FTS=67 +PRED_IN=68 +PRED_LIKE=69 +QUALIFIER=70 +QUERY=71 +QUOTED_STRING=72 +RPAREN=73 +SCORE=74 +SELECT=75 +SIGNED_INTEGER=76 +SINGLE_VALUED_PROPERTY=77 +SORT_SPECIFICATION=78 +SOURCE=79 +STAR=80 +STRING_LITERAL=81 +TABLE=82 +TABLE_REF=83 +TILDA=84 +TIMESTAMP=85 +TRUE=86 +WHERE=87 +WS=88 +ZERO_DIGIT=89 diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMISLexer.java b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMISLexer.java new file mode 100644 index 0000000000..ef0305f707 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMISLexer.java @@ -0,0 +1,3418 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +// $ANTLR 3.5.2 W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g 2015-06-18 19:38:04 + + package org.alfresco.repo.search.impl.parsers; + import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; + + +import org.antlr.runtime.*; +import java.util.Stack; +import java.util.List; +import java.util.ArrayList; + +@SuppressWarnings("all") +public class CMISLexer extends Lexer { + public static final int EOF=-1; + public static final int ALL_COLUMNS=4; + public static final int AND=5; + public static final int ANY=6; + public static final int AS=7; + public static final int ASC=8; + public static final int BOOLEAN_LITERAL=9; + public static final int BY=10; + public static final int COLON=11; + public static final int COLUMN=12; + public static final int COLUMNS=13; + public static final int COLUMN_REF=14; + public static final int COMMA=15; + public static final int CONJUNCTION=16; + public static final int CONTAINS=17; + public static final int DATETIME_LITERAL=18; + public static final int DECIMAL_INTEGER_LITERAL=19; + public static final int DECIMAL_NUMERAL=20; + public static final int DESC=21; + public static final int DIGIT=22; + public static final int DISJUNCTION=23; + public static final int DOT=24; + public static final int DOTDOT=25; + public static final int DOTSTAR=26; + public static final int DOUBLE_QUOTE=27; + public static final int E=28; + public static final int EQUALS=29; + public static final int EXPONENT=30; + public static final int FALSE=31; + public static final int FLOATING_POINT_LITERAL=32; + public static final int FROM=33; + public static final int FUNCTION=34; + public static final int GREATERTHAN=35; + public static final int GREATERTHANOREQUALS=36; + public static final int ID=37; + public static final int IN=38; + public static final int INNER=39; + public static final int IN_FOLDER=40; + public static final int IN_TREE=41; + public static final int IS=42; + public static final int JOIN=43; + public static final int LEFT=44; + public static final int LESSTHAN=45; + public static final int LESSTHANOREQUALS=46; + public static final int LIKE=47; + public static final int LIST=48; + public static final int LPAREN=49; + public static final int MINUS=50; + public static final int NEGATION=51; + public static final int NON_ZERO_DIGIT=52; + public static final int NOT=53; + public static final int NOTEQUALS=54; + public static final int NULL=55; + public static final int NUMERIC_LITERAL=56; + public static final int ON=57; + public static final int OR=58; + public static final int ORDER=59; + public static final int OUTER=60; + public static final int PARAMETER=61; + public static final int PLUS=62; + public static final int PRED_CHILD=63; + public static final int PRED_COMPARISON=64; + public static final int PRED_DESCENDANT=65; + public static final int PRED_EXISTS=66; + public static final int PRED_FTS=67; + public static final int PRED_IN=68; + public static final int PRED_LIKE=69; + public static final int QUALIFIER=70; + public static final int QUERY=71; + public static final int QUOTED_STRING=72; + public static final int RPAREN=73; + public static final int SCORE=74; + public static final int SELECT=75; + public static final int SIGNED_INTEGER=76; + public static final int SINGLE_VALUED_PROPERTY=77; + public static final int SORT_SPECIFICATION=78; + public static final int SOURCE=79; + public static final int STAR=80; + public static final int STRING_LITERAL=81; + public static final int TABLE=82; + public static final int TABLE_REF=83; + public static final int TILDA=84; + public static final int TIMESTAMP=85; + public static final int TRUE=86; + public static final int WHERE=87; + public static final int WS=88; + public static final int ZERO_DIGIT=89; + + public Token nextToken() { + while (true) + { + state.token = null; + state.channel = Token.DEFAULT_CHANNEL; + state.tokenStartCharIndex = input.index(); + state.tokenStartCharPositionInLine = input.getCharPositionInLine(); + state.tokenStartLine = input.getLine(); + state.text = null; + if ( input.LA(1)==CharStream.EOF ) + { + return getEOFToken(); + } + try + { + mTokens(); + if ( state.token==null ) + { + emit(); + } + else if ( state.token==Token.SKIP_TOKEN ) + { + continue; + } + return state.token; + } + catch (RecognitionException re) + { + throw new CmisInvalidArgumentException(getErrorString(re), re); + } + } + } + + public String getErrorString(RecognitionException e) + { + String hdr = getErrorHeader(e); + String msg = getErrorMessage(e, this.getTokenNames()); + return hdr+" "+msg; + } + + + // delegates + // delegators + public Lexer[] getDelegates() { + return new Lexer[] {}; + } + + public CMISLexer() {} + public CMISLexer(CharStream input) { + this(input, new RecognizerSharedState()); + } + public CMISLexer(CharStream input, RecognizerSharedState state) { + super(input,state); + } + @Override public String getGrammarFileName() { return "W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g"; } + + // $ANTLR start "QUOTED_STRING" + public final void mQUOTED_STRING() throws RecognitionException { + try { + int _type = QUOTED_STRING; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:853:9: ( '\\'' (~ ( '\\'' | '\\\\' ) | '\\\\' . )* '\\'' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:854:9: '\\'' (~ ( '\\'' | '\\\\' ) | '\\\\' . )* '\\'' + { + match('\''); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:855:9: (~ ( '\\'' | '\\\\' ) | '\\\\' . )* + loop1: + while (true) { + int alt1=3; + int LA1_0 = input.LA(1); + if ( ((LA1_0 >= '\u0000' && LA1_0 <= '&')||(LA1_0 >= '(' && LA1_0 <= '[')||(LA1_0 >= ']' && LA1_0 <= '\uFFFF')) ) { + alt1=1; + } + else if ( (LA1_0=='\\') ) { + alt1=2; + } + + switch (alt1) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:856:17: ~ ( '\\'' | '\\\\' ) + { + if ( (input.LA(1) >= '\u0000' && input.LA(1) <= '&')||(input.LA(1) >= '(' && input.LA(1) <= '[')||(input.LA(1) >= ']' && input.LA(1) <= '\uFFFF') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:857:19: '\\\\' . + { + match('\\'); + matchAny(); + } + break; + + default : + break loop1; + } + } + + match('\''); + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "QUOTED_STRING" + + // $ANTLR start "SELECT" + public final void mSELECT() throws RecognitionException { + try { + int _type = SELECT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:863:9: ( ( 'S' | 's' ) ( 'E' | 'e' ) ( 'L' | 'l' ) ( 'E' | 'e' ) ( 'C' | 'c' ) ( 'T' | 't' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:864:9: ( 'S' | 's' ) ( 'E' | 'e' ) ( 'L' | 'l' ) ( 'E' | 'e' ) ( 'C' | 'c' ) ( 'T' | 't' ) + { + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='L'||input.LA(1)=='l' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='C'||input.LA(1)=='c' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='T'||input.LA(1)=='t' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "SELECT" + + // $ANTLR start "AS" + public final void mAS() throws RecognitionException { + try { + int _type = AS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:891:9: ( ( 'A' | 'a' ) ( 'S' | 's' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:892:9: ( 'A' | 'a' ) ( 'S' | 's' ) + { + if ( input.LA(1)=='A'||input.LA(1)=='a' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "AS" + + // $ANTLR start "FROM" + public final void mFROM() throws RecognitionException { + try { + int _type = FROM; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:903:9: ( ( 'F' | 'f' ) ( 'R' | 'r' ) ( 'O' | 'o' ) ( 'M' | 'm' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:904:9: ( 'F' | 'f' ) ( 'R' | 'r' ) ( 'O' | 'o' ) ( 'M' | 'm' ) + { + if ( input.LA(1)=='F'||input.LA(1)=='f' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='M'||input.LA(1)=='m' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "FROM" + + // $ANTLR start "JOIN" + public final void mJOIN() throws RecognitionException { + try { + int _type = JOIN; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:923:9: ( ( 'J' | 'j' ) ( 'O' | 'o' ) ( 'I' | 'i' ) ( 'N' | 'n' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:924:9: ( 'J' | 'j' ) ( 'O' | 'o' ) ( 'I' | 'i' ) ( 'N' | 'n' ) + { + if ( input.LA(1)=='J'||input.LA(1)=='j' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='I'||input.LA(1)=='i' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "JOIN" + + // $ANTLR start "INNER" + public final void mINNER() throws RecognitionException { + try { + int _type = INNER; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:943:9: ( ( 'I' | 'i' ) ( 'N' | 'n' ) ( 'N' | 'n' ) ( 'E' | 'e' ) ( 'R' | 'r' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:944:9: ( 'I' | 'i' ) ( 'N' | 'n' ) ( 'N' | 'n' ) ( 'E' | 'e' ) ( 'R' | 'r' ) + { + if ( input.LA(1)=='I'||input.LA(1)=='i' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "INNER" + + // $ANTLR start "LEFT" + public final void mLEFT() throws RecognitionException { + try { + int _type = LEFT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:967:9: ( ( 'L' | 'l' ) ( 'E' | 'e' ) ( 'F' | 'f' ) ( 'T' | 't' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:968:9: ( 'L' | 'l' ) ( 'E' | 'e' ) ( 'F' | 'f' ) ( 'T' | 't' ) + { + if ( input.LA(1)=='L'||input.LA(1)=='l' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='F'||input.LA(1)=='f' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='T'||input.LA(1)=='t' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "LEFT" + + // $ANTLR start "OUTER" + public final void mOUTER() throws RecognitionException { + try { + int _type = OUTER; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:987:9: ( ( 'O' | 'o' ) ( 'U' | 'u' ) ( 'T' | 't' ) ( 'E' | 'e' ) ( 'R' | 'r' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:988:9: ( 'O' | 'o' ) ( 'U' | 'u' ) ( 'T' | 't' ) ( 'E' | 'e' ) ( 'R' | 'r' ) + { + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='U'||input.LA(1)=='u' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='T'||input.LA(1)=='t' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "OUTER" + + // $ANTLR start "ON" + public final void mON() throws RecognitionException { + try { + int _type = ON; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1011:9: ( ( 'O' | 'o' ) ( 'N' | 'n' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1012:9: ( 'O' | 'o' ) ( 'N' | 'n' ) + { + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "ON" + + // $ANTLR start "WHERE" + public final void mWHERE() throws RecognitionException { + try { + int _type = WHERE; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1023:9: ( ( 'W' | 'w' ) ( 'H' | 'h' ) ( 'E' | 'e' ) ( 'R' | 'r' ) ( 'E' | 'e' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1024:9: ( 'W' | 'w' ) ( 'H' | 'h' ) ( 'E' | 'e' ) ( 'R' | 'r' ) ( 'E' | 'e' ) + { + if ( input.LA(1)=='W'||input.LA(1)=='w' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='H'||input.LA(1)=='h' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "WHERE" + + // $ANTLR start "OR" + public final void mOR() throws RecognitionException { + try { + int _type = OR; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1047:9: ( ( 'O' | 'o' ) ( 'R' | 'r' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1048:9: ( 'O' | 'o' ) ( 'R' | 'r' ) + { + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "OR" + + // $ANTLR start "AND" + public final void mAND() throws RecognitionException { + try { + int _type = AND; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1059:9: ( ( 'A' | 'a' ) ( 'N' | 'n' ) ( 'D' | 'd' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1060:9: ( 'A' | 'a' ) ( 'N' | 'n' ) ( 'D' | 'd' ) + { + if ( input.LA(1)=='A'||input.LA(1)=='a' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='D'||input.LA(1)=='d' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "AND" + + // $ANTLR start "NOT" + public final void mNOT() throws RecognitionException { + try { + int _type = NOT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1075:9: ( ( 'N' | 'n' ) ( 'O' | 'o' ) ( 'T' | 't' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1076:9: ( 'N' | 'n' ) ( 'O' | 'o' ) ( 'T' | 't' ) + { + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='T'||input.LA(1)=='t' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "NOT" + + // $ANTLR start "IN" + public final void mIN() throws RecognitionException { + try { + int _type = IN; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1091:9: ( ( 'I' | 'i' ) ( 'N' | 'n' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1092:9: ( 'I' | 'i' ) ( 'N' | 'n' ) + { + if ( input.LA(1)=='I'||input.LA(1)=='i' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "IN" + + // $ANTLR start "LIKE" + public final void mLIKE() throws RecognitionException { + try { + int _type = LIKE; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1103:9: ( ( 'L' | 'l' ) ( 'I' | 'i' ) ( 'K' | 'k' ) ( 'E' | 'e' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1104:9: ( 'L' | 'l' ) ( 'I' | 'i' ) ( 'K' | 'k' ) ( 'E' | 'e' ) + { + if ( input.LA(1)=='L'||input.LA(1)=='l' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='I'||input.LA(1)=='i' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='K'||input.LA(1)=='k' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "LIKE" + + // $ANTLR start "IS" + public final void mIS() throws RecognitionException { + try { + int _type = IS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1123:9: ( ( 'I' | 'i' ) ( 'S' | 's' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1124:9: ( 'I' | 'i' ) ( 'S' | 's' ) + { + if ( input.LA(1)=='I'||input.LA(1)=='i' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "IS" + + // $ANTLR start "NULL" + public final void mNULL() throws RecognitionException { + try { + int _type = NULL; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1135:9: ( ( 'N' | 'n' ) ( 'U' | 'u' ) ( 'L' | 'l' ) ( 'L' | 'l' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1136:9: ( 'N' | 'n' ) ( 'U' | 'u' ) ( 'L' | 'l' ) ( 'L' | 'l' ) + { + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='U'||input.LA(1)=='u' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='L'||input.LA(1)=='l' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='L'||input.LA(1)=='l' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "NULL" + + // $ANTLR start "ANY" + public final void mANY() throws RecognitionException { + try { + int _type = ANY; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1155:9: ( ( 'A' | 'a' ) ( 'N' | 'n' ) ( 'Y' | 'y' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1156:9: ( 'A' | 'a' ) ( 'N' | 'n' ) ( 'Y' | 'y' ) + { + if ( input.LA(1)=='A'||input.LA(1)=='a' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='Y'||input.LA(1)=='y' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "ANY" + + // $ANTLR start "CONTAINS" + public final void mCONTAINS() throws RecognitionException { + try { + int _type = CONTAINS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1171:9: ( ( 'C' | 'c' ) ( 'O' | 'o' ) ( 'N' | 'n' ) ( 'T' | 't' ) ( 'A' | 'a' ) ( 'I' | 'i' ) ( 'N' | 'n' ) ( 'S' | 's' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1172:9: ( 'C' | 'c' ) ( 'O' | 'o' ) ( 'N' | 'n' ) ( 'T' | 't' ) ( 'A' | 'a' ) ( 'I' | 'i' ) ( 'N' | 'n' ) ( 'S' | 's' ) + { + if ( input.LA(1)=='C'||input.LA(1)=='c' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='T'||input.LA(1)=='t' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='A'||input.LA(1)=='a' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='I'||input.LA(1)=='i' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "CONTAINS" + + // $ANTLR start "IN_FOLDER" + public final void mIN_FOLDER() throws RecognitionException { + try { + int _type = IN_FOLDER; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1207:9: ( ( 'I' | 'i' ) ( 'N' | 'n' ) '_' ( 'F' | 'f' ) ( 'O' | 'o' ) ( 'L' | 'l' ) ( 'D' | 'd' ) ( 'E' | 'e' ) ( 'R' | 'r' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1208:9: ( 'I' | 'i' ) ( 'N' | 'n' ) '_' ( 'F' | 'f' ) ( 'O' | 'o' ) ( 'L' | 'l' ) ( 'D' | 'd' ) ( 'E' | 'e' ) ( 'R' | 'r' ) + { + if ( input.LA(1)=='I'||input.LA(1)=='i' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + match('_'); + if ( input.LA(1)=='F'||input.LA(1)=='f' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='L'||input.LA(1)=='l' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='D'||input.LA(1)=='d' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "IN_FOLDER" + + // $ANTLR start "IN_TREE" + public final void mIN_TREE() throws RecognitionException { + try { + int _type = IN_TREE; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1244:9: ( ( 'I' | 'i' ) ( 'N' | 'n' ) '_' ( 'T' | 't' ) ( 'R' | 'r' ) ( 'E' | 'e' ) ( 'E' | 'e' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1245:9: ( 'I' | 'i' ) ( 'N' | 'n' ) '_' ( 'T' | 't' ) ( 'R' | 'r' ) ( 'E' | 'e' ) ( 'E' | 'e' ) + { + if ( input.LA(1)=='I'||input.LA(1)=='i' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + match('_'); + if ( input.LA(1)=='T'||input.LA(1)=='t' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "IN_TREE" + + // $ANTLR start "ORDER" + public final void mORDER() throws RecognitionException { + try { + int _type = ORDER; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1273:9: ( ( 'O' | 'o' ) ( 'R' | 'r' ) ( 'D' | 'd' ) ( 'E' | 'e' ) ( 'R' | 'r' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1274:9: ( 'O' | 'o' ) ( 'R' | 'r' ) ( 'D' | 'd' ) ( 'E' | 'e' ) ( 'R' | 'r' ) + { + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='D'||input.LA(1)=='d' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "ORDER" + + // $ANTLR start "BY" + public final void mBY() throws RecognitionException { + try { + int _type = BY; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1297:9: ( ( 'B' | 'b' ) ( 'Y' | 'y' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1298:9: ( 'B' | 'b' ) ( 'Y' | 'y' ) + { + if ( input.LA(1)=='B'||input.LA(1)=='b' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='Y'||input.LA(1)=='y' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "BY" + + // $ANTLR start "ASC" + public final void mASC() throws RecognitionException { + try { + int _type = ASC; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1309:9: ( ( 'A' | 'a' ) ( 'S' | 's' ) ( 'C' | 'c' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1310:9: ( 'A' | 'a' ) ( 'S' | 's' ) ( 'C' | 'c' ) + { + if ( input.LA(1)=='A'||input.LA(1)=='a' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='C'||input.LA(1)=='c' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "ASC" + + // $ANTLR start "DESC" + public final void mDESC() throws RecognitionException { + try { + int _type = DESC; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1325:9: ( ( 'D' | 'd' ) ( 'E' | 'e' ) ( 'S' | 's' ) ( 'C' | 'c' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1326:9: ( 'D' | 'd' ) ( 'E' | 'e' ) ( 'S' | 's' ) ( 'C' | 'c' ) + { + if ( input.LA(1)=='D'||input.LA(1)=='d' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='C'||input.LA(1)=='c' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DESC" + + // $ANTLR start "TIMESTAMP" + public final void mTIMESTAMP() throws RecognitionException { + try { + int _type = TIMESTAMP; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1345:9: ( ( 'T' | 't' ) ( 'I' | 'i' ) ( 'M' | 'm' ) ( 'E' | 'e' ) ( 'S' | 's' ) ( 'T' | 't' ) ( 'A' | 'a' ) ( 'M' | 'm' ) ( 'P' | 'p' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1346:9: ( 'T' | 't' ) ( 'I' | 'i' ) ( 'M' | 'm' ) ( 'E' | 'e' ) ( 'S' | 's' ) ( 'T' | 't' ) ( 'A' | 'a' ) ( 'M' | 'm' ) ( 'P' | 'p' ) + { + if ( input.LA(1)=='T'||input.LA(1)=='t' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='I'||input.LA(1)=='i' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='M'||input.LA(1)=='m' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='T'||input.LA(1)=='t' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='A'||input.LA(1)=='a' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='M'||input.LA(1)=='m' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='P'||input.LA(1)=='p' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "TIMESTAMP" + + // $ANTLR start "TRUE" + public final void mTRUE() throws RecognitionException { + try { + int _type = TRUE; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1385:9: ( ( 'T' | 't' ) ( 'R' | 'r' ) ( 'U' | 'u' ) ( 'E' | 'e' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1386:9: ( 'T' | 't' ) ( 'R' | 'r' ) ( 'U' | 'u' ) ( 'E' | 'e' ) + { + if ( input.LA(1)=='T'||input.LA(1)=='t' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='U'||input.LA(1)=='u' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "TRUE" + + // $ANTLR start "FALSE" + public final void mFALSE() throws RecognitionException { + try { + int _type = FALSE; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1405:9: ( ( 'F' | 'f' ) ( 'A' | 'a' ) ( 'L' | 'l' ) ( 'S' | 's' ) ( 'E' | 'e' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1406:9: ( 'F' | 'f' ) ( 'A' | 'a' ) ( 'L' | 'l' ) ( 'S' | 's' ) ( 'E' | 'e' ) + { + if ( input.LA(1)=='F'||input.LA(1)=='f' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='A'||input.LA(1)=='a' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='L'||input.LA(1)=='l' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "FALSE" + + // $ANTLR start "SCORE" + public final void mSCORE() throws RecognitionException { + try { + int _type = SCORE; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1429:9: ( ( 'S' | 's' ) ( 'C' | 'c' ) ( 'O' | 'o' ) ( 'R' | 'r' ) ( 'E' | 'e' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1430:9: ( 'S' | 's' ) ( 'C' | 'c' ) ( 'O' | 'o' ) ( 'R' | 'r' ) ( 'E' | 'e' ) + { + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='C'||input.LA(1)=='c' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "SCORE" + + // $ANTLR start "LPAREN" + public final void mLPAREN() throws RecognitionException { + try { + int _type = LPAREN; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1453:9: ( '(' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1454:9: '(' + { + match('('); + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "LPAREN" + + // $ANTLR start "RPAREN" + public final void mRPAREN() throws RecognitionException { + try { + int _type = RPAREN; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1458:9: ( ')' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1459:9: ')' + { + match(')'); + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "RPAREN" + + // $ANTLR start "STAR" + public final void mSTAR() throws RecognitionException { + try { + int _type = STAR; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1463:9: ( '*' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1464:9: '*' + { + match('*'); + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "STAR" + + // $ANTLR start "COMMA" + public final void mCOMMA() throws RecognitionException { + try { + int _type = COMMA; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1468:9: ( ',' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1469:9: ',' + { + match(','); + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "COMMA" + + // $ANTLR start "DOTSTAR" + public final void mDOTSTAR() throws RecognitionException { + try { + int _type = DOTSTAR; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1473:9: ( '.*' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1474:9: '.*' + { + match(".*"); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DOTSTAR" + + // $ANTLR start "DOT" + public final void mDOT() throws RecognitionException { + try { + int _type = DOT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1478:9: ( '.' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1479:9: '.' + { + match('.'); + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DOT" + + // $ANTLR start "DOTDOT" + public final void mDOTDOT() throws RecognitionException { + try { + int _type = DOTDOT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1483:9: ( '..' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1484:9: '..' + { + match(".."); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DOTDOT" + + // $ANTLR start "EQUALS" + public final void mEQUALS() throws RecognitionException { + try { + int _type = EQUALS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1488:9: ( '=' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1489:9: '=' + { + match('='); + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "EQUALS" + + // $ANTLR start "TILDA" + public final void mTILDA() throws RecognitionException { + try { + int _type = TILDA; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1493:9: ( '~' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1494:9: '~' + { + match('~'); + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "TILDA" + + // $ANTLR start "NOTEQUALS" + public final void mNOTEQUALS() throws RecognitionException { + try { + int _type = NOTEQUALS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1498:9: ( '<>' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1499:9: '<>' + { + match("<>"); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "NOTEQUALS" + + // $ANTLR start "GREATERTHAN" + public final void mGREATERTHAN() throws RecognitionException { + try { + int _type = GREATERTHAN; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1503:9: ( '>' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1504:9: '>' + { + match('>'); + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "GREATERTHAN" + + // $ANTLR start "LESSTHAN" + public final void mLESSTHAN() throws RecognitionException { + try { + int _type = LESSTHAN; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1508:9: ( '<' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1509:9: '<' + { + match('<'); + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "LESSTHAN" + + // $ANTLR start "GREATERTHANOREQUALS" + public final void mGREATERTHANOREQUALS() throws RecognitionException { + try { + int _type = GREATERTHANOREQUALS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1513:9: ( '>=' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1514:9: '>=' + { + match(">="); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "GREATERTHANOREQUALS" + + // $ANTLR start "LESSTHANOREQUALS" + public final void mLESSTHANOREQUALS() throws RecognitionException { + try { + int _type = LESSTHANOREQUALS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1518:9: ( '<=' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1519:9: '<=' + { + match("<="); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "LESSTHANOREQUALS" + + // $ANTLR start "COLON" + public final void mCOLON() throws RecognitionException { + try { + int _type = COLON; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1523:9: ( ':' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1524:9: ':' + { + match(':'); + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "COLON" + + // $ANTLR start "DOUBLE_QUOTE" + public final void mDOUBLE_QUOTE() throws RecognitionException { + try { + int _type = DOUBLE_QUOTE; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1528:9: ( '\"' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1529:9: '\"' + { + match('\"'); + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DOUBLE_QUOTE" + + // $ANTLR start "DECIMAL_INTEGER_LITERAL" + public final void mDECIMAL_INTEGER_LITERAL() throws RecognitionException { + try { + int _type = DECIMAL_INTEGER_LITERAL; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1537:9: ( ( PLUS | MINUS )? DECIMAL_NUMERAL ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1538:9: ( PLUS | MINUS )? DECIMAL_NUMERAL + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1538:9: ( PLUS | MINUS )? + int alt2=2; + int LA2_0 = input.LA(1); + if ( (LA2_0=='+'||LA2_0=='-') ) { + alt2=1; + } + switch (alt2) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( input.LA(1)=='+'||input.LA(1)=='-' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + mDECIMAL_NUMERAL(); + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DECIMAL_INTEGER_LITERAL" + + // $ANTLR start "FLOATING_POINT_LITERAL" + public final void mFLOATING_POINT_LITERAL() throws RecognitionException { + try { + int _type = FLOATING_POINT_LITERAL; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1550:9: ( ( PLUS | MINUS )? ( DIGIT )+ DOT ( DIGIT )* ( EXPONENT )? | ( PLUS | MINUS )? DOT ( DIGIT )+ ( EXPONENT )? | ( PLUS | MINUS )? ( DIGIT )+ EXPONENT ) + int alt12=3; + alt12 = dfa12.predict(input); + switch (alt12) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1551:9: ( PLUS | MINUS )? ( DIGIT )+ DOT ( DIGIT )* ( EXPONENT )? + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1551:9: ( PLUS | MINUS )? + int alt3=2; + int LA3_0 = input.LA(1); + if ( (LA3_0=='+'||LA3_0=='-') ) { + alt3=1; + } + switch (alt3) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( input.LA(1)=='+'||input.LA(1)=='-' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1555:9: ( DIGIT )+ + int cnt4=0; + loop4: + while (true) { + int alt4=2; + int LA4_0 = input.LA(1); + if ( ((LA4_0 >= '0' && LA4_0 <= '9')) ) { + alt4=1; + } + + switch (alt4) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + if ( cnt4 >= 1 ) break loop4; + EarlyExitException eee = new EarlyExitException(4, input); + throw eee; + } + cnt4++; + } + + mDOT(); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1555:20: ( DIGIT )* + loop5: + while (true) { + int alt5=2; + int LA5_0 = input.LA(1); + if ( ((LA5_0 >= '0' && LA5_0 <= '9')) ) { + alt5=1; + } + + switch (alt5) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + break loop5; + } + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1555:27: ( EXPONENT )? + int alt6=2; + int LA6_0 = input.LA(1); + if ( (LA6_0=='E'||LA6_0=='e') ) { + alt6=1; + } + switch (alt6) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1555:27: EXPONENT + { + mEXPONENT(); + + } + break; + + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1557:9: ( PLUS | MINUS )? DOT ( DIGIT )+ ( EXPONENT )? + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1557:9: ( PLUS | MINUS )? + int alt7=2; + int LA7_0 = input.LA(1); + if ( (LA7_0=='+'||LA7_0=='-') ) { + alt7=1; + } + switch (alt7) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( input.LA(1)=='+'||input.LA(1)=='-' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + mDOT(); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1561:13: ( DIGIT )+ + int cnt8=0; + loop8: + while (true) { + int alt8=2; + int LA8_0 = input.LA(1); + if ( ((LA8_0 >= '0' && LA8_0 <= '9')) ) { + alt8=1; + } + + switch (alt8) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + if ( cnt8 >= 1 ) break loop8; + EarlyExitException eee = new EarlyExitException(8, input); + throw eee; + } + cnt8++; + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1561:20: ( EXPONENT )? + int alt9=2; + int LA9_0 = input.LA(1); + if ( (LA9_0=='E'||LA9_0=='e') ) { + alt9=1; + } + switch (alt9) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1561:20: EXPONENT + { + mEXPONENT(); + + } + break; + + } + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1563:9: ( PLUS | MINUS )? ( DIGIT )+ EXPONENT + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1563:9: ( PLUS | MINUS )? + int alt10=2; + int LA10_0 = input.LA(1); + if ( (LA10_0=='+'||LA10_0=='-') ) { + alt10=1; + } + switch (alt10) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( input.LA(1)=='+'||input.LA(1)=='-' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1567:9: ( DIGIT )+ + int cnt11=0; + loop11: + while (true) { + int alt11=2; + int LA11_0 = input.LA(1); + if ( ((LA11_0 >= '0' && LA11_0 <= '9')) ) { + alt11=1; + } + + switch (alt11) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + if ( cnt11 >= 1 ) break loop11; + EarlyExitException eee = new EarlyExitException(11, input); + throw eee; + } + cnt11++; + } + + mEXPONENT(); + + } + break; + + } + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "FLOATING_POINT_LITERAL" + + // $ANTLR start "ID" + public final void mID() throws RecognitionException { + try { + int _type = ID; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1577:9: ( ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | ':' | '$' | '#' )* ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1578:9: ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | ':' | '$' | '#' )* + { + if ( (input.LA(1) >= 'A' && input.LA(1) <= 'Z')||input.LA(1)=='_'||(input.LA(1) >= 'a' && input.LA(1) <= 'z') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1583:9: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | ':' | '$' | '#' )* + loop13: + while (true) { + int alt13=2; + int LA13_0 = input.LA(1); + if ( ((LA13_0 >= '#' && LA13_0 <= '$')||(LA13_0 >= '0' && LA13_0 <= ':')||(LA13_0 >= 'A' && LA13_0 <= 'Z')||LA13_0=='_'||(LA13_0 >= 'a' && LA13_0 <= 'z')) ) { + alt13=1; + } + + switch (alt13) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( (input.LA(1) >= '#' && input.LA(1) <= '$')||(input.LA(1) >= '0' && input.LA(1) <= ':')||(input.LA(1) >= 'A' && input.LA(1) <= 'Z')||input.LA(1)=='_'||(input.LA(1) >= 'a' && input.LA(1) <= 'z') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + break loop13; + } + } + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "ID" + + // $ANTLR start "WS" + public final void mWS() throws RecognitionException { + try { + int _type = WS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1592:9: ( ( ' ' | '\\t' | '\\r' | '\\n' )+ ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1593:9: ( ' ' | '\\t' | '\\r' | '\\n' )+ + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1593:9: ( ' ' | '\\t' | '\\r' | '\\n' )+ + int cnt14=0; + loop14: + while (true) { + int alt14=2; + int LA14_0 = input.LA(1); + if ( ((LA14_0 >= '\t' && LA14_0 <= '\n')||LA14_0=='\r'||LA14_0==' ') ) { + alt14=1; + } + + switch (alt14) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( (input.LA(1) >= '\t' && input.LA(1) <= '\n')||input.LA(1)=='\r'||input.LA(1)==' ' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + if ( cnt14 >= 1 ) break loop14; + EarlyExitException eee = new EarlyExitException(14, input); + throw eee; + } + cnt14++; + } + + _channel = HIDDEN; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "WS" + + // $ANTLR start "DECIMAL_NUMERAL" + public final void mDECIMAL_NUMERAL() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1611:9: ( ZERO_DIGIT | NON_ZERO_DIGIT ( DIGIT )* ) + int alt16=2; + int LA16_0 = input.LA(1); + if ( (LA16_0=='0') ) { + alt16=1; + } + else if ( ((LA16_0 >= '1' && LA16_0 <= '9')) ) { + alt16=2; + } + + else { + NoViableAltException nvae = + new NoViableAltException("", 16, 0, input); + throw nvae; + } + + switch (alt16) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1612:9: ZERO_DIGIT + { + mZERO_DIGIT(); + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1613:11: NON_ZERO_DIGIT ( DIGIT )* + { + mNON_ZERO_DIGIT(); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1613:26: ( DIGIT )* + loop15: + while (true) { + int alt15=2; + int LA15_0 = input.LA(1); + if ( ((LA15_0 >= '0' && LA15_0 <= '9')) ) { + alt15=1; + } + + switch (alt15) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + break loop15; + } + } + + } + break; + + } + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DECIMAL_NUMERAL" + + // $ANTLR start "DIGIT" + public final void mDIGIT() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1615:9: ( ZERO_DIGIT | NON_ZERO_DIGIT ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DIGIT" + + // $ANTLR start "ZERO_DIGIT" + public final void mZERO_DIGIT() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1622:9: ( '0' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1623:9: '0' + { + match('0'); + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "ZERO_DIGIT" + + // $ANTLR start "NON_ZERO_DIGIT" + public final void mNON_ZERO_DIGIT() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1628:9: ( '1' .. '9' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( (input.LA(1) >= '1' && input.LA(1) <= '9') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "NON_ZERO_DIGIT" + + // $ANTLR start "PLUS" + public final void mPLUS() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1634:9: ( '+' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1635:9: '+' + { + match('+'); + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "PLUS" + + // $ANTLR start "MINUS" + public final void mMINUS() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1640:9: ( '-' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1641:9: '-' + { + match('-'); + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "MINUS" + + // $ANTLR start "E" + public final void mE() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1646:9: ( ( 'e' | 'E' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "E" + + // $ANTLR start "EXPONENT" + public final void mEXPONENT() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1659:9: ( E SIGNED_INTEGER ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1660:9: E SIGNED_INTEGER + { + mE(); + + mSIGNED_INTEGER(); + + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "EXPONENT" + + // $ANTLR start "SIGNED_INTEGER" + public final void mSIGNED_INTEGER() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1665:9: ( ( PLUS | MINUS )? ( DIGIT )+ ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1666:9: ( PLUS | MINUS )? ( DIGIT )+ + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1666:9: ( PLUS | MINUS )? + int alt17=2; + int LA17_0 = input.LA(1); + if ( (LA17_0=='+'||LA17_0=='-') ) { + alt17=1; + } + switch (alt17) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( input.LA(1)=='+'||input.LA(1)=='-' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1670:9: ( DIGIT )+ + int cnt18=0; + loop18: + while (true) { + int alt18=2; + int LA18_0 = input.LA(1); + if ( ((LA18_0 >= '0' && LA18_0 <= '9')) ) { + alt18=1; + } + + switch (alt18) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + if ( cnt18 >= 1 ) break loop18; + EarlyExitException eee = new EarlyExitException(18, input); + throw eee; + } + cnt18++; + } + + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "SIGNED_INTEGER" + + @Override + public void mTokens() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:8: ( QUOTED_STRING | SELECT | AS | FROM | JOIN | INNER | LEFT | OUTER | ON | WHERE | OR | AND | NOT | IN | LIKE | IS | NULL | ANY | CONTAINS | IN_FOLDER | IN_TREE | ORDER | BY | ASC | DESC | TIMESTAMP | TRUE | FALSE | SCORE | LPAREN | RPAREN | STAR | COMMA | DOTSTAR | DOT | DOTDOT | EQUALS | TILDA | NOTEQUALS | GREATERTHAN | LESSTHAN | GREATERTHANOREQUALS | LESSTHANOREQUALS | COLON | DOUBLE_QUOTE | DECIMAL_INTEGER_LITERAL | FLOATING_POINT_LITERAL | ID | WS ) + int alt19=49; + alt19 = dfa19.predict(input); + switch (alt19) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:10: QUOTED_STRING + { + mQUOTED_STRING(); + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:24: SELECT + { + mSELECT(); + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:31: AS + { + mAS(); + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:34: FROM + { + mFROM(); + + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:39: JOIN + { + mJOIN(); + + } + break; + case 6 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:44: INNER + { + mINNER(); + + } + break; + case 7 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:50: LEFT + { + mLEFT(); + + } + break; + case 8 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:55: OUTER + { + mOUTER(); + + } + break; + case 9 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:61: ON + { + mON(); + + } + break; + case 10 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:64: WHERE + { + mWHERE(); + + } + break; + case 11 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:70: OR + { + mOR(); + + } + break; + case 12 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:73: AND + { + mAND(); + + } + break; + case 13 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:77: NOT + { + mNOT(); + + } + break; + case 14 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:81: IN + { + mIN(); + + } + break; + case 15 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:84: LIKE + { + mLIKE(); + + } + break; + case 16 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:89: IS + { + mIS(); + + } + break; + case 17 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:92: NULL + { + mNULL(); + + } + break; + case 18 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:97: ANY + { + mANY(); + + } + break; + case 19 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:101: CONTAINS + { + mCONTAINS(); + + } + break; + case 20 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:110: IN_FOLDER + { + mIN_FOLDER(); + + } + break; + case 21 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:120: IN_TREE + { + mIN_TREE(); + + } + break; + case 22 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:128: ORDER + { + mORDER(); + + } + break; + case 23 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:134: BY + { + mBY(); + + } + break; + case 24 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:137: ASC + { + mASC(); + + } + break; + case 25 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:141: DESC + { + mDESC(); + + } + break; + case 26 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:146: TIMESTAMP + { + mTIMESTAMP(); + + } + break; + case 27 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:156: TRUE + { + mTRUE(); + + } + break; + case 28 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:161: FALSE + { + mFALSE(); + + } + break; + case 29 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:167: SCORE + { + mSCORE(); + + } + break; + case 30 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:173: LPAREN + { + mLPAREN(); + + } + break; + case 31 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:180: RPAREN + { + mRPAREN(); + + } + break; + case 32 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:187: STAR + { + mSTAR(); + + } + break; + case 33 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:192: COMMA + { + mCOMMA(); + + } + break; + case 34 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:198: DOTSTAR + { + mDOTSTAR(); + + } + break; + case 35 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:206: DOT + { + mDOT(); + + } + break; + case 36 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:210: DOTDOT + { + mDOTDOT(); + + } + break; + case 37 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:217: EQUALS + { + mEQUALS(); + + } + break; + case 38 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:224: TILDA + { + mTILDA(); + + } + break; + case 39 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:230: NOTEQUALS + { + mNOTEQUALS(); + + } + break; + case 40 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:240: GREATERTHAN + { + mGREATERTHAN(); + + } + break; + case 41 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:252: LESSTHAN + { + mLESSTHAN(); + + } + break; + case 42 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:261: GREATERTHANOREQUALS + { + mGREATERTHANOREQUALS(); + + } + break; + case 43 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:281: LESSTHANOREQUALS + { + mLESSTHANOREQUALS(); + + } + break; + case 44 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:298: COLON + { + mCOLON(); + + } + break; + case 45 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:304: DOUBLE_QUOTE + { + mDOUBLE_QUOTE(); + + } + break; + case 46 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:317: DECIMAL_INTEGER_LITERAL + { + mDECIMAL_INTEGER_LITERAL(); + + } + break; + case 47 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:341: FLOATING_POINT_LITERAL + { + mFLOATING_POINT_LITERAL(); + + } + break; + case 48 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:364: ID + { + mID(); + + } + break; + case 49 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:1:367: WS + { + mWS(); + + } + break; + + } + } + + + protected DFA12 dfa12 = new DFA12(this); + protected DFA19 dfa19 = new DFA19(this); + static final String DFA12_eotS = + "\6\uffff"; + static final String DFA12_eofS = + "\6\uffff"; + static final String DFA12_minS = + "\1\53\2\56\3\uffff"; + static final String DFA12_maxS = + "\2\71\1\145\3\uffff"; + static final String DFA12_acceptS = + "\3\uffff\1\2\1\1\1\3"; + static final String DFA12_specialS = + "\6\uffff}>"; + static final String[] DFA12_transitionS = { + "\1\1\1\uffff\1\1\1\3\1\uffff\12\2", + "\1\3\1\uffff\12\2", + "\1\4\1\uffff\12\2\13\uffff\1\5\37\uffff\1\5", + "", + "", + "" + }; + + static final short[] DFA12_eot = DFA.unpackEncodedString(DFA12_eotS); + static final short[] DFA12_eof = DFA.unpackEncodedString(DFA12_eofS); + static final char[] DFA12_min = DFA.unpackEncodedStringToUnsignedChars(DFA12_minS); + static final char[] DFA12_max = DFA.unpackEncodedStringToUnsignedChars(DFA12_maxS); + static final short[] DFA12_accept = DFA.unpackEncodedString(DFA12_acceptS); + static final short[] DFA12_special = DFA.unpackEncodedString(DFA12_specialS); + static final short[][] DFA12_transition; + + static { + int numStates = DFA12_transitionS.length; + DFA12_transition = new short[numStates][]; + for (int i=0; i"; + static final String[] DFA19_transitionS = { + "\2\36\2\uffff\1\36\22\uffff\1\36\1\uffff\1\31\4\uffff\1\1\1\17\1\20\1"+ + "\21\1\32\1\22\1\32\1\23\1\uffff\1\33\11\34\1\30\1\uffff\1\26\1\24\1\27"+ + "\2\uffff\1\3\1\14\1\13\1\15\1\35\1\4\2\35\1\6\1\5\1\35\1\7\1\35\1\12"+ + "\1\10\3\35\1\2\1\16\2\35\1\11\3\35\4\uffff\1\35\1\uffff\1\3\1\14\1\13"+ + "\1\15\1\35\1\4\2\35\1\6\1\5\1\35\1\7\1\35\1\12\1\10\3\35\1\2\1\16\2\35"+ + "\1\11\3\35\3\uffff\1\25", + "", + "\1\40\1\uffff\1\37\35\uffff\1\40\1\uffff\1\37", + "\1\42\4\uffff\1\41\32\uffff\1\42\4\uffff\1\41", + "\1\44\20\uffff\1\43\16\uffff\1\44\20\uffff\1\43", + "\1\45\37\uffff\1\45", + "\1\46\4\uffff\1\47\32\uffff\1\46\4\uffff\1\47", + "\1\50\3\uffff\1\51\33\uffff\1\50\3\uffff\1\51", + "\1\53\3\uffff\1\54\2\uffff\1\52\30\uffff\1\53\3\uffff\1\54\2\uffff\1"+ + "\52", + "\1\55\37\uffff\1\55", + "\1\56\5\uffff\1\57\31\uffff\1\56\5\uffff\1\57", + "\1\60\37\uffff\1\60", + "\1\61\37\uffff\1\61", + "\1\62\37\uffff\1\62", + "\1\63\10\uffff\1\64\26\uffff\1\63\10\uffff\1\64", + "", + "", + "", + "", + "\1\65\3\uffff\1\66\1\uffff\12\70", + "", + "", + "\1\72\1\71", + "\1\74", + "", + "", + "\1\70\1\uffff\1\33\11\34", + "\1\70\1\uffff\12\70\13\uffff\1\70\37\uffff\1\70", + "\1\70\1\uffff\12\77\13\uffff\1\70\37\uffff\1\70", + "", + "", + "\1\100\37\uffff\1\100", + "\1\101\37\uffff\1\101", + "\2\35\13\uffff\13\35\6\uffff\2\35\1\102\27\35\4\uffff\1\35\1\uffff\2"+ + "\35\1\102\27\35", + "\1\104\24\uffff\1\105\12\uffff\1\104\24\uffff\1\105", + "\1\106\37\uffff\1\106", + "\1\107\37\uffff\1\107", + "\1\110\37\uffff\1\110", + "\2\35\13\uffff\13\35\6\uffff\15\35\1\111\14\35\4\uffff\1\112\1\uffff"+ + "\15\35\1\111\14\35", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\1\115\37\uffff\1\115", + "\1\116\37\uffff\1\116", + "\1\117\37\uffff\1\117", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\2\35\13\uffff\13\35\6\uffff\3\35\1\121\26\35\4\uffff\1\35\1\uffff\3"+ + "\35\1\121\26\35", + "\1\123\37\uffff\1\123", + "\1\124\37\uffff\1\124", + "\1\125\37\uffff\1\125", + "\1\126\37\uffff\1\126", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\1\130\37\uffff\1\130", + "\1\131\37\uffff\1\131", + "\1\132\37\uffff\1\132", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\70\1\uffff\12\77\13\uffff\1\70\37\uffff\1\70", + "\1\133\37\uffff\1\133", + "\1\134\37\uffff\1\134", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\1\140\37\uffff\1\140", + "\1\141\37\uffff\1\141", + "\1\142\37\uffff\1\142", + "\1\143\37\uffff\1\143", + "\1\144\15\uffff\1\145\21\uffff\1\144\15\uffff\1\145", + "", + "", + "\1\146\37\uffff\1\146", + "\1\147\37\uffff\1\147", + "\1\150\37\uffff\1\150", + "", + "\1\151\37\uffff\1\151", + "", + "\1\152\37\uffff\1\152", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\1\154\37\uffff\1\154", + "\1\155\37\uffff\1\155", + "", + "\1\156\37\uffff\1\156", + "\1\157\37\uffff\1\157", + "\1\160\37\uffff\1\160", + "\1\161\37\uffff\1\161", + "\1\162\37\uffff\1\162", + "", + "", + "", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\1\164\37\uffff\1\164", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\1\166\37\uffff\1\166", + "\1\167\37\uffff\1\167", + "\1\170\37\uffff\1\170", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\1\173\37\uffff\1\173", + "\1\174\37\uffff\1\174", + "\1\175\37\uffff\1\175", + "", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\1\177\37\uffff\1\177", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\1\u0081\37\uffff\1\u0081", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\1\u0083\37\uffff\1\u0083", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\1\u0087\37\uffff\1\u0087", + "\1\u0088\37\uffff\1\u0088", + "", + "", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "", + "\1\u008c\37\uffff\1\u008c", + "", + "\1\u008d\37\uffff\1\u008d", + "", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "", + "", + "", + "\1\u008f\37\uffff\1\u008f", + "\1\u0090\37\uffff\1\u0090", + "", + "", + "", + "\1\u0091\37\uffff\1\u0091", + "\1\u0092\37\uffff\1\u0092", + "", + "\1\u0093\37\uffff\1\u0093", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\1\u0095\37\uffff\1\u0095", + "\1\u0096\37\uffff\1\u0096", + "\1\u0097\37\uffff\1\u0097", + "", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "\1\u0099\37\uffff\1\u0099", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "", + "\2\35\13\uffff\13\35\6\uffff\32\35\4\uffff\1\35\1\uffff\32\35", + "", + "" + }; + + static final short[] DFA19_eot = DFA.unpackEncodedString(DFA19_eotS); + static final short[] DFA19_eof = DFA.unpackEncodedString(DFA19_eofS); + static final char[] DFA19_min = DFA.unpackEncodedStringToUnsignedChars(DFA19_minS); + static final char[] DFA19_max = DFA.unpackEncodedStringToUnsignedChars(DFA19_maxS); + static final short[] DFA19_accept = DFA.unpackEncodedString(DFA19_acceptS); + static final short[] DFA19_special = DFA.unpackEncodedString(DFA19_specialS); + static final short[][] DFA19_transition; + + static { + int numStates = DFA19_transitionS.length; + DFA19_transition = new short[numStates][]; + for (int i=0; i. + * #L% + */ +// $ANTLR 3.5.2 W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g 2015-06-18 19:38:02 + + package org.alfresco.repo.search.impl.parsers; + import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; + + +import org.antlr.runtime.*; +import java.util.Stack; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; + +import org.antlr.runtime.tree.*; + + +@SuppressWarnings("all") +public class CMISParser extends Parser { + public static final String[] tokenNames = new String[] { + "", "", "", "", "ALL_COLUMNS", "AND", "ANY", "AS", + "ASC", "BOOLEAN_LITERAL", "BY", "COLON", "COLUMN", "COLUMNS", "COLUMN_REF", + "COMMA", "CONJUNCTION", "CONTAINS", "DATETIME_LITERAL", "DECIMAL_INTEGER_LITERAL", + "DECIMAL_NUMERAL", "DESC", "DIGIT", "DISJUNCTION", "DOT", "DOTDOT", "DOTSTAR", + "DOUBLE_QUOTE", "E", "EQUALS", "EXPONENT", "FALSE", "FLOATING_POINT_LITERAL", + "FROM", "FUNCTION", "GREATERTHAN", "GREATERTHANOREQUALS", "ID", "IN", + "INNER", "IN_FOLDER", "IN_TREE", "IS", "JOIN", "LEFT", "LESSTHAN", "LESSTHANOREQUALS", + "LIKE", "LIST", "LPAREN", "MINUS", "NEGATION", "NON_ZERO_DIGIT", "NOT", + "NOTEQUALS", "NULL", "NUMERIC_LITERAL", "ON", "OR", "ORDER", "OUTER", + "PARAMETER", "PLUS", "PRED_CHILD", "PRED_COMPARISON", "PRED_DESCENDANT", + "PRED_EXISTS", "PRED_FTS", "PRED_IN", "PRED_LIKE", "QUALIFIER", "QUERY", + "QUOTED_STRING", "RPAREN", "SCORE", "SELECT", "SIGNED_INTEGER", "SINGLE_VALUED_PROPERTY", + "SORT_SPECIFICATION", "SOURCE", "STAR", "STRING_LITERAL", "TABLE", "TABLE_REF", + "TILDA", "TIMESTAMP", "TRUE", "WHERE", "WS", "ZERO_DIGIT" + }; + public static final int EOF=-1; + public static final int ALL_COLUMNS=4; + public static final int AND=5; + public static final int ANY=6; + public static final int AS=7; + public static final int ASC=8; + public static final int BOOLEAN_LITERAL=9; + public static final int BY=10; + public static final int COLON=11; + public static final int COLUMN=12; + public static final int COLUMNS=13; + public static final int COLUMN_REF=14; + public static final int COMMA=15; + public static final int CONJUNCTION=16; + public static final int CONTAINS=17; + public static final int DATETIME_LITERAL=18; + public static final int DECIMAL_INTEGER_LITERAL=19; + public static final int DECIMAL_NUMERAL=20; + public static final int DESC=21; + public static final int DIGIT=22; + public static final int DISJUNCTION=23; + public static final int DOT=24; + public static final int DOTDOT=25; + public static final int DOTSTAR=26; + public static final int DOUBLE_QUOTE=27; + public static final int E=28; + public static final int EQUALS=29; + public static final int EXPONENT=30; + public static final int FALSE=31; + public static final int FLOATING_POINT_LITERAL=32; + public static final int FROM=33; + public static final int FUNCTION=34; + public static final int GREATERTHAN=35; + public static final int GREATERTHANOREQUALS=36; + public static final int ID=37; + public static final int IN=38; + public static final int INNER=39; + public static final int IN_FOLDER=40; + public static final int IN_TREE=41; + public static final int IS=42; + public static final int JOIN=43; + public static final int LEFT=44; + public static final int LESSTHAN=45; + public static final int LESSTHANOREQUALS=46; + public static final int LIKE=47; + public static final int LIST=48; + public static final int LPAREN=49; + public static final int MINUS=50; + public static final int NEGATION=51; + public static final int NON_ZERO_DIGIT=52; + public static final int NOT=53; + public static final int NOTEQUALS=54; + public static final int NULL=55; + public static final int NUMERIC_LITERAL=56; + public static final int ON=57; + public static final int OR=58; + public static final int ORDER=59; + public static final int OUTER=60; + public static final int PARAMETER=61; + public static final int PLUS=62; + public static final int PRED_CHILD=63; + public static final int PRED_COMPARISON=64; + public static final int PRED_DESCENDANT=65; + public static final int PRED_EXISTS=66; + public static final int PRED_FTS=67; + public static final int PRED_IN=68; + public static final int PRED_LIKE=69; + public static final int QUALIFIER=70; + public static final int QUERY=71; + public static final int QUOTED_STRING=72; + public static final int RPAREN=73; + public static final int SCORE=74; + public static final int SELECT=75; + public static final int SIGNED_INTEGER=76; + public static final int SINGLE_VALUED_PROPERTY=77; + public static final int SORT_SPECIFICATION=78; + public static final int SOURCE=79; + public static final int STAR=80; + public static final int STRING_LITERAL=81; + public static final int TABLE=82; + public static final int TABLE_REF=83; + public static final int TILDA=84; + public static final int TIMESTAMP=85; + public static final int TRUE=86; + public static final int WHERE=87; + public static final int WS=88; + public static final int ZERO_DIGIT=89; + + // delegates + public Parser[] getDelegates() { + return new Parser[] {}; + } + + // delegators + + + public CMISParser(TokenStream input) { + this(input, new RecognizerSharedState()); + } + public CMISParser(TokenStream input, RecognizerSharedState state) { + super(input, state); + } + + protected TreeAdaptor adaptor = new CommonTreeAdaptor(); + + public void setTreeAdaptor(TreeAdaptor adaptor) { + this.adaptor = adaptor; + } + public TreeAdaptor getTreeAdaptor() { + return adaptor; + } + @Override public String[] getTokenNames() { return CMISParser.tokenNames; } + @Override public String getGrammarFileName() { return "W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g"; } + + + private Stack paraphrases = new Stack(); + + private boolean strict = false; + + /** + * CMIS strict + */ + public boolean strict() + { + return strict; + } + + public void setStrict(boolean strict) + { + this.strict = strict; + } + + protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException + { + throw new MismatchedTokenException(ttype, input); + } + + public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException + { + throw e; + } + + public String getErrorMessage(RecognitionException e, String[] tokenNames) + { + List stack = getRuleInvocationStack(e, this.getClass().getName()); + String msg = e.getMessage(); + if ( e instanceof UnwantedTokenException ) + { + UnwantedTokenException ute = (UnwantedTokenException)e; + String tokenName=""; + if ( ute.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[ute.expecting]; + } + msg = "extraneous input " + getTokenErrorDisplay(ute.getUnexpectedToken()) + + " expecting "+tokenName; + } + else if ( e instanceof MissingTokenException ) + { + MissingTokenException mte = (MissingTokenException)e; + String tokenName=""; + if ( mte.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mte.expecting]; + } + msg = "missing " + tokenName+" at " + getTokenErrorDisplay(e.token) + + " (" + getLongTokenErrorDisplay(e.token) +")"; + } + else if ( e instanceof MismatchedTokenException ) + { + MismatchedTokenException mte = (MismatchedTokenException)e; + String tokenName=""; + if ( mte.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mte.expecting]; + } + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting " + tokenName +" (" + getLongTokenErrorDisplay(e.token) + ")"; + } + else if ( e instanceof MismatchedTreeNodeException ) + { + MismatchedTreeNodeException mtne = (MismatchedTreeNodeException)e; + String tokenName=""; + if ( mtne.expecting==Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mtne.expecting]; + } + msg = "mismatched tree node: " + mtne.node + " expecting " + tokenName; + } + else if ( e instanceof NoViableAltException ) + { + NoViableAltException nvae = (NoViableAltException)e; + msg = "no viable alternative at input " + getTokenErrorDisplay(e.token) + + "\n\t (decision=" + nvae.decisionNumber + + " state " + nvae.stateNumber + ")" + + " decision=<<" + nvae.grammarDecisionDescription + ">>"; + } + else if ( e instanceof EarlyExitException ) + { + //EarlyExitException eee = (EarlyExitException)e; + // for development, can add "(decision="+eee.decisionNumber+")" + msg = "required (...)+ loop did not match anything at input " + getTokenErrorDisplay(e.token); + } + else if ( e instanceof MismatchedSetException ) + { + MismatchedSetException mse = (MismatchedSetException)e; + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting set " + mse.expecting; + } + else if ( e instanceof MismatchedNotSetException ) + { + MismatchedNotSetException mse = (MismatchedNotSetException)e; + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting set " + mse.expecting; + } + else if ( e instanceof FailedPredicateException ) + { + FailedPredicateException fpe = (FailedPredicateException)e; + msg = "rule " + fpe.ruleName + " failed predicate: {" + fpe.predicateText + "}?"; + } + + if(paraphrases.size() > 0) + { + String paraphrase = (String)paraphrases.peek(); + msg = msg+" "+paraphrase; + } + return msg +"\n\t"+stack; + } + + public String getLongTokenErrorDisplay(Token t) + { + return t.toString(); + } + + + public String getErrorString(RecognitionException e) + { + String hdr = getErrorHeader(e); + String msg = getErrorMessage(e, this.getTokenNames()); + return hdr+" "+msg; + } + + + public static class query_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "query" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:285:1: query : SELECT selectList fromClause ( whereClause )? ( orderByClause )? EOF -> ^( QUERY selectList fromClause ( whereClause )? ( orderByClause )? ) ; + public final CMISParser.query_return query() throws RecognitionException { + CMISParser.query_return retval = new CMISParser.query_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token SELECT1=null; + Token EOF6=null; + ParserRuleReturnScope selectList2 =null; + ParserRuleReturnScope fromClause3 =null; + ParserRuleReturnScope whereClause4 =null; + ParserRuleReturnScope orderByClause5 =null; + + Object SELECT1_tree=null; + Object EOF6_tree=null; + RewriteRuleTokenStream stream_EOF=new RewriteRuleTokenStream(adaptor,"token EOF"); + RewriteRuleTokenStream stream_SELECT=new RewriteRuleTokenStream(adaptor,"token SELECT"); + RewriteRuleSubtreeStream stream_whereClause=new RewriteRuleSubtreeStream(adaptor,"rule whereClause"); + RewriteRuleSubtreeStream stream_orderByClause=new RewriteRuleSubtreeStream(adaptor,"rule orderByClause"); + RewriteRuleSubtreeStream stream_selectList=new RewriteRuleSubtreeStream(adaptor,"rule selectList"); + RewriteRuleSubtreeStream stream_fromClause=new RewriteRuleSubtreeStream(adaptor,"rule fromClause"); + + + paraphrases.push("in query"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:294:9: ( SELECT selectList fromClause ( whereClause )? ( orderByClause )? EOF -> ^( QUERY selectList fromClause ( whereClause )? ( orderByClause )? ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:295:9: SELECT selectList fromClause ( whereClause )? ( orderByClause )? EOF + { + SELECT1=(Token)match(input,SELECT,FOLLOW_SELECT_in_query415); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_SELECT.add(SELECT1); + + pushFollow(FOLLOW_selectList_in_query417); + selectList2=selectList(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_selectList.add(selectList2.getTree()); + pushFollow(FOLLOW_fromClause_in_query419); + fromClause3=fromClause(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fromClause.add(fromClause3.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:295:38: ( whereClause )? + int alt1=2; + int LA1_0 = input.LA(1); + if ( (LA1_0==WHERE) ) { + alt1=1; + } + switch (alt1) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:295:38: whereClause + { + pushFollow(FOLLOW_whereClause_in_query421); + whereClause4=whereClause(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_whereClause.add(whereClause4.getTree()); + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:295:51: ( orderByClause )? + int alt2=2; + int LA2_0 = input.LA(1); + if ( (LA2_0==ORDER) ) { + alt2=1; + } + switch (alt2) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:295:51: orderByClause + { + pushFollow(FOLLOW_orderByClause_in_query424); + orderByClause5=orderByClause(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_orderByClause.add(orderByClause5.getTree()); + } + break; + + } + + EOF6=(Token)match(input,EOF,FOLLOW_EOF_in_query427); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_EOF.add(EOF6); + + // AST REWRITE + // elements: orderByClause, fromClause, selectList, whereClause + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 296:17: -> ^( QUERY selectList fromClause ( whereClause )? ( orderByClause )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:297:25: ^( QUERY selectList fromClause ( whereClause )? ( orderByClause )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(QUERY, "QUERY"), root_1); + adaptor.addChild(root_1, stream_selectList.nextTree()); + adaptor.addChild(root_1, stream_fromClause.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:297:55: ( whereClause )? + if ( stream_whereClause.hasNext() ) { + adaptor.addChild(root_1, stream_whereClause.nextTree()); + } + stream_whereClause.reset(); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:297:68: ( orderByClause )? + if ( stream_orderByClause.hasNext() ) { + adaptor.addChild(root_1, stream_orderByClause.nextTree()); + } + stream_orderByClause.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + if ( state.backtracking==0 ) { + paraphrases.pop(); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "query" + + + public static class selectList_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "selectList" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:300:1: selectList : ( STAR -> ^( ALL_COLUMNS ) | selectSubList ( COMMA selectSubList )* -> ^( COLUMNS ( selectSubList )+ ) ); + public final CMISParser.selectList_return selectList() throws RecognitionException { + CMISParser.selectList_return retval = new CMISParser.selectList_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token STAR7=null; + Token COMMA9=null; + ParserRuleReturnScope selectSubList8 =null; + ParserRuleReturnScope selectSubList10 =null; + + Object STAR7_tree=null; + Object COMMA9_tree=null; + RewriteRuleTokenStream stream_STAR=new RewriteRuleTokenStream(adaptor,"token STAR"); + RewriteRuleTokenStream stream_COMMA=new RewriteRuleTokenStream(adaptor,"token COMMA"); + RewriteRuleSubtreeStream stream_selectSubList=new RewriteRuleSubtreeStream(adaptor,"rule selectSubList"); + + + paraphrases.push("in select list"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:309:9: ( STAR -> ^( ALL_COLUMNS ) | selectSubList ( COMMA selectSubList )* -> ^( COLUMNS ( selectSubList )+ ) ) + int alt4=2; + int LA4_0 = input.LA(1); + if ( (LA4_0==STAR) ) { + alt4=1; + } + else if ( (LA4_0==ID) ) { + alt4=2; + } + else if ( (LA4_0==DOUBLE_QUOTE) && ((strict == false))) { + alt4=2; + } + else if ( (LA4_0==SCORE) ) { + alt4=2; + } + else if ( ((LA4_0 >= AND && LA4_0 <= ASC)||LA4_0==BY||LA4_0==CONTAINS||LA4_0==DESC||LA4_0==FALSE||LA4_0==FROM||(LA4_0 >= IN && LA4_0 <= LEFT)||LA4_0==LIKE||LA4_0==NOT||LA4_0==NULL||(LA4_0 >= ON && LA4_0 <= OUTER)||LA4_0==SELECT||(LA4_0 >= TIMESTAMP && LA4_0 <= WHERE)) && ((strict == false))) { + alt4=2; + } + + switch (alt4) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:310:9: STAR + { + STAR7=(Token)match(input,STAR,FOLLOW_STAR_in_selectList526); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_STAR.add(STAR7); + + // AST REWRITE + // elements: + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 311:17: -> ^( ALL_COLUMNS ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:312:25: ^( ALL_COLUMNS ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(ALL_COLUMNS, "ALL_COLUMNS"), root_1); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:313:11: selectSubList ( COMMA selectSubList )* + { + pushFollow(FOLLOW_selectSubList_in_selectList584); + selectSubList8=selectSubList(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_selectSubList.add(selectSubList8.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:313:25: ( COMMA selectSubList )* + loop3: + while (true) { + int alt3=2; + int LA3_0 = input.LA(1); + if ( (LA3_0==COMMA) ) { + alt3=1; + } + + switch (alt3) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:313:26: COMMA selectSubList + { + COMMA9=(Token)match(input,COMMA,FOLLOW_COMMA_in_selectList587); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_COMMA.add(COMMA9); + + pushFollow(FOLLOW_selectSubList_in_selectList589); + selectSubList10=selectSubList(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_selectSubList.add(selectSubList10.getTree()); + } + break; + + default : + break loop3; + } + } + + // AST REWRITE + // elements: selectSubList + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 314:17: -> ^( COLUMNS ( selectSubList )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:315:25: ^( COLUMNS ( selectSubList )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(COLUMNS, "COLUMNS"), root_1); + if ( !(stream_selectSubList.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_selectSubList.hasNext() ) { + adaptor.addChild(root_1, stream_selectSubList.nextTree()); + } + stream_selectSubList.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + if ( state.backtracking==0 ) { + paraphrases.pop(); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "selectList" + + + public static class selectSubList_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "selectSubList" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:318:1: selectSubList : ( valueExpression ( ( AS )? columnName )? -> ^( COLUMN valueExpression ( columnName )? ) | qualifier DOTSTAR -> ^( ALL_COLUMNS qualifier ) ); + public final CMISParser.selectSubList_return selectSubList() throws RecognitionException { + CMISParser.selectSubList_return retval = new CMISParser.selectSubList_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token AS12=null; + Token DOTSTAR15=null; + ParserRuleReturnScope valueExpression11 =null; + ParserRuleReturnScope columnName13 =null; + ParserRuleReturnScope qualifier14 =null; + + Object AS12_tree=null; + Object DOTSTAR15_tree=null; + RewriteRuleTokenStream stream_AS=new RewriteRuleTokenStream(adaptor,"token AS"); + RewriteRuleTokenStream stream_DOTSTAR=new RewriteRuleTokenStream(adaptor,"token DOTSTAR"); + RewriteRuleSubtreeStream stream_valueExpression=new RewriteRuleSubtreeStream(adaptor,"rule valueExpression"); + RewriteRuleSubtreeStream stream_columnName=new RewriteRuleSubtreeStream(adaptor,"rule columnName"); + RewriteRuleSubtreeStream stream_qualifier=new RewriteRuleSubtreeStream(adaptor,"rule qualifier"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:319:9: ( valueExpression ( ( AS )? columnName )? -> ^( COLUMN valueExpression ( columnName )? ) | qualifier DOTSTAR -> ^( ALL_COLUMNS qualifier ) ) + int alt7=2; + int LA7_0 = input.LA(1); + if ( (LA7_0==ID) ) { + int LA7_1 = input.LA(2); + if ( (LA7_1==AS||LA7_1==COMMA||LA7_1==DOT||LA7_1==DOUBLE_QUOTE||LA7_1==FROM||LA7_1==ID) ) { + alt7=1; + } + else if ( (LA7_1==LPAREN) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_1==DOTSTAR) ) { + alt7=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 7, 1, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + else if ( (LA7_0==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_2 = input.LA(2); + if ( (LA7_2==SELECT) && ((strict == false))) { + int LA7_8 = input.LA(3); + if ( (LA7_8==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==AS) && ((strict == false))) { + int LA7_9 = input.LA(3); + if ( (LA7_9==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==FROM) && ((strict == false))) { + int LA7_10 = input.LA(3); + if ( (LA7_10==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==JOIN) && ((strict == false))) { + int LA7_11 = input.LA(3); + if ( (LA7_11==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==INNER) && ((strict == false))) { + int LA7_12 = input.LA(3); + if ( (LA7_12==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==LEFT) && ((strict == false))) { + int LA7_13 = input.LA(3); + if ( (LA7_13==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==OUTER) && ((strict == false))) { + int LA7_14 = input.LA(3); + if ( (LA7_14==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==ON) && ((strict == false))) { + int LA7_15 = input.LA(3); + if ( (LA7_15==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==WHERE) && ((strict == false))) { + int LA7_16 = input.LA(3); + if ( (LA7_16==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==OR) && ((strict == false))) { + int LA7_17 = input.LA(3); + if ( (LA7_17==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==AND) && ((strict == false))) { + int LA7_18 = input.LA(3); + if ( (LA7_18==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==NOT) && ((strict == false))) { + int LA7_19 = input.LA(3); + if ( (LA7_19==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==IN) && ((strict == false))) { + int LA7_20 = input.LA(3); + if ( (LA7_20==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==LIKE) && ((strict == false))) { + int LA7_21 = input.LA(3); + if ( (LA7_21==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==IS) && ((strict == false))) { + int LA7_22 = input.LA(3); + if ( (LA7_22==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==NULL) && ((strict == false))) { + int LA7_23 = input.LA(3); + if ( (LA7_23==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==ANY) && ((strict == false))) { + int LA7_24 = input.LA(3); + if ( (LA7_24==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==CONTAINS) && ((strict == false))) { + int LA7_25 = input.LA(3); + if ( (LA7_25==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==IN_FOLDER) && ((strict == false))) { + int LA7_26 = input.LA(3); + if ( (LA7_26==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==IN_TREE) && ((strict == false))) { + int LA7_27 = input.LA(3); + if ( (LA7_27==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==ORDER) && ((strict == false))) { + int LA7_28 = input.LA(3); + if ( (LA7_28==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==BY) && ((strict == false))) { + int LA7_29 = input.LA(3); + if ( (LA7_29==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==ASC) && ((strict == false))) { + int LA7_30 = input.LA(3); + if ( (LA7_30==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==DESC) && ((strict == false))) { + int LA7_31 = input.LA(3); + if ( (LA7_31==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==TIMESTAMP) && ((strict == false))) { + int LA7_32 = input.LA(3); + if ( (LA7_32==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==TRUE) && ((strict == false))) { + int LA7_33 = input.LA(3); + if ( (LA7_33==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==FALSE) && ((strict == false))) { + int LA7_34 = input.LA(3); + if ( (LA7_34==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==SCORE) && ((strict == false))) { + int LA7_35 = input.LA(3); + if ( (LA7_35==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + else if ( (LA7_2==ID) && ((strict == false))) { + int LA7_36 = input.LA(3); + if ( (LA7_36==DOUBLE_QUOTE) && ((strict == false))) { + int LA7_37 = input.LA(4); + if ( (LA7_37==AS||LA7_37==COMMA||LA7_37==DOT||LA7_37==DOUBLE_QUOTE||LA7_37==FROM||LA7_37==ID) && ((strict == false))) { + alt7=1; + } + else if ( (LA7_37==DOTSTAR) && ((strict == false))) { + alt7=2; + } + + } + + } + + } + else if ( (LA7_0==SCORE) ) { + alt7=1; + } + else if ( ((LA7_0 >= AND && LA7_0 <= ASC)||LA7_0==BY||LA7_0==CONTAINS||LA7_0==DESC||LA7_0==FALSE||LA7_0==FROM||(LA7_0 >= IN && LA7_0 <= LEFT)||LA7_0==LIKE||LA7_0==NOT||LA7_0==NULL||(LA7_0 >= ON && LA7_0 <= OUTER)||LA7_0==SELECT||(LA7_0 >= TIMESTAMP && LA7_0 <= WHERE)) && ((strict == false))) { + alt7=1; + } + + switch (alt7) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:320:9: valueExpression ( ( AS )? columnName )? + { + pushFollow(FOLLOW_valueExpression_in_selectSubList673); + valueExpression11=valueExpression(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_valueExpression.add(valueExpression11.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:320:25: ( ( AS )? columnName )? + int alt6=2; + int LA6_0 = input.LA(1); + if ( (LA6_0==AS||LA6_0==ID) ) { + alt6=1; + } + else if ( (LA6_0==DOUBLE_QUOTE) && ((strict == false))) { + alt6=1; + } + switch (alt6) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:320:26: ( AS )? columnName + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:320:26: ( AS )? + int alt5=2; + int LA5_0 = input.LA(1); + if ( (LA5_0==AS) ) { + alt5=1; + } + switch (alt5) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:320:26: AS + { + AS12=(Token)match(input,AS,FOLLOW_AS_in_selectSubList676); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_AS.add(AS12); + + } + break; + + } + + pushFollow(FOLLOW_columnName_in_selectSubList679); + columnName13=columnName(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_columnName.add(columnName13.getTree()); + } + break; + + } + + // AST REWRITE + // elements: valueExpression, columnName + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 321:17: -> ^( COLUMN valueExpression ( columnName )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:322:25: ^( COLUMN valueExpression ( columnName )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(COLUMN, "COLUMN"), root_1); + adaptor.addChild(root_1, stream_valueExpression.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:322:50: ( columnName )? + if ( stream_columnName.hasNext() ) { + adaptor.addChild(root_1, stream_columnName.nextTree()); + } + stream_columnName.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:323:11: qualifier DOTSTAR + { + pushFollow(FOLLOW_qualifier_in_selectSubList744); + qualifier14=qualifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_qualifier.add(qualifier14.getTree()); + DOTSTAR15=(Token)match(input,DOTSTAR,FOLLOW_DOTSTAR_in_selectSubList746); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DOTSTAR.add(DOTSTAR15); + + // AST REWRITE + // elements: qualifier + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 324:17: -> ^( ALL_COLUMNS qualifier ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:325:25: ^( ALL_COLUMNS qualifier ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(ALL_COLUMNS, "ALL_COLUMNS"), root_1); + adaptor.addChild(root_1, stream_qualifier.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "selectSubList" + + + public static class valueExpression_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "valueExpression" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:328:1: valueExpression : ( columnReference -> columnReference | valueFunction -> valueFunction ); + public final CMISParser.valueExpression_return valueExpression() throws RecognitionException { + CMISParser.valueExpression_return retval = new CMISParser.valueExpression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope columnReference16 =null; + ParserRuleReturnScope valueFunction17 =null; + + RewriteRuleSubtreeStream stream_valueFunction=new RewriteRuleSubtreeStream(adaptor,"rule valueFunction"); + RewriteRuleSubtreeStream stream_columnReference=new RewriteRuleSubtreeStream(adaptor,"rule columnReference"); + + + paraphrases.push("in value expression"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:337:9: ( columnReference -> columnReference | valueFunction -> valueFunction ) + int alt8=2; + int LA8_0 = input.LA(1); + if ( (LA8_0==ID) ) { + int LA8_1 = input.LA(2); + if ( (LA8_1==AS||LA8_1==COMMA||LA8_1==DOT||LA8_1==DOUBLE_QUOTE||LA8_1==EQUALS||LA8_1==FROM||(LA8_1 >= GREATERTHAN && LA8_1 <= ID)||(LA8_1 >= LESSTHAN && LA8_1 <= LESSTHANOREQUALS)||LA8_1==NOTEQUALS) ) { + alt8=1; + } + else if ( (LA8_1==LPAREN) && ((strict == false))) { + alt8=2; + } + + } + else if ( (LA8_0==DOUBLE_QUOTE) && ((strict == false))) { + alt8=1; + } + else if ( (LA8_0==SCORE) ) { + alt8=2; + } + else if ( ((LA8_0 >= AND && LA8_0 <= ASC)||LA8_0==BY||LA8_0==CONTAINS||LA8_0==DESC||LA8_0==FALSE||LA8_0==FROM||(LA8_0 >= IN && LA8_0 <= LEFT)||LA8_0==LIKE||LA8_0==NOT||LA8_0==NULL||(LA8_0 >= ON && LA8_0 <= OUTER)||LA8_0==SELECT||(LA8_0 >= TIMESTAMP && LA8_0 <= WHERE)) && ((strict == false))) { + alt8=2; + } + + switch (alt8) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:338:9: columnReference + { + pushFollow(FOLLOW_columnReference_in_valueExpression837); + columnReference16=columnReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_columnReference.add(columnReference16.getTree()); + // AST REWRITE + // elements: columnReference + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 339:17: -> columnReference + { + adaptor.addChild(root_0, stream_columnReference.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:340:11: valueFunction + { + pushFollow(FOLLOW_valueFunction_in_valueExpression869); + valueFunction17=valueFunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_valueFunction.add(valueFunction17.getTree()); + // AST REWRITE + // elements: valueFunction + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 341:17: -> valueFunction + { + adaptor.addChild(root_0, stream_valueFunction.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + if ( state.backtracking==0 ) { + paraphrases.pop(); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "valueExpression" + + + public static class columnReference_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "columnReference" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:344:1: columnReference : ( qualifier DOT )? columnName -> ^( COLUMN_REF columnName ( qualifier )? ) ; + public final CMISParser.columnReference_return columnReference() throws RecognitionException { + CMISParser.columnReference_return retval = new CMISParser.columnReference_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token DOT19=null; + ParserRuleReturnScope qualifier18 =null; + ParserRuleReturnScope columnName20 =null; + + Object DOT19_tree=null; + RewriteRuleTokenStream stream_DOT=new RewriteRuleTokenStream(adaptor,"token DOT"); + RewriteRuleSubtreeStream stream_columnName=new RewriteRuleSubtreeStream(adaptor,"rule columnName"); + RewriteRuleSubtreeStream stream_qualifier=new RewriteRuleSubtreeStream(adaptor,"rule qualifier"); + + + paraphrases.push("in column reference"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:353:9: ( ( qualifier DOT )? columnName -> ^( COLUMN_REF columnName ( qualifier )? ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:354:9: ( qualifier DOT )? columnName + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:354:9: ( qualifier DOT )? + int alt9=2; + int LA9_0 = input.LA(1); + if ( (LA9_0==ID) ) { + int LA9_1 = input.LA(2); + if ( (LA9_1==DOT) ) { + alt9=1; + } + } + else if ( (LA9_0==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_2 = input.LA(2); + if ( (LA9_2==SELECT) && ((strict == false))) { + int LA9_5 = input.LA(3); + if ( (LA9_5==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==AS) && ((strict == false))) { + int LA9_6 = input.LA(3); + if ( (LA9_6==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==FROM) && ((strict == false))) { + int LA9_7 = input.LA(3); + if ( (LA9_7==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==JOIN) && ((strict == false))) { + int LA9_8 = input.LA(3); + if ( (LA9_8==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==INNER) && ((strict == false))) { + int LA9_9 = input.LA(3); + if ( (LA9_9==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==LEFT) && ((strict == false))) { + int LA9_10 = input.LA(3); + if ( (LA9_10==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==OUTER) && ((strict == false))) { + int LA9_11 = input.LA(3); + if ( (LA9_11==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==ON) && ((strict == false))) { + int LA9_12 = input.LA(3); + if ( (LA9_12==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==WHERE) && ((strict == false))) { + int LA9_13 = input.LA(3); + if ( (LA9_13==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==OR) && ((strict == false))) { + int LA9_14 = input.LA(3); + if ( (LA9_14==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==AND) && ((strict == false))) { + int LA9_15 = input.LA(3); + if ( (LA9_15==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==NOT) && ((strict == false))) { + int LA9_16 = input.LA(3); + if ( (LA9_16==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==IN) && ((strict == false))) { + int LA9_17 = input.LA(3); + if ( (LA9_17==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==LIKE) && ((strict == false))) { + int LA9_18 = input.LA(3); + if ( (LA9_18==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==IS) && ((strict == false))) { + int LA9_19 = input.LA(3); + if ( (LA9_19==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==NULL) && ((strict == false))) { + int LA9_20 = input.LA(3); + if ( (LA9_20==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==ANY) && ((strict == false))) { + int LA9_21 = input.LA(3); + if ( (LA9_21==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==CONTAINS) && ((strict == false))) { + int LA9_22 = input.LA(3); + if ( (LA9_22==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==IN_FOLDER) && ((strict == false))) { + int LA9_23 = input.LA(3); + if ( (LA9_23==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==IN_TREE) && ((strict == false))) { + int LA9_24 = input.LA(3); + if ( (LA9_24==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==ORDER) && ((strict == false))) { + int LA9_25 = input.LA(3); + if ( (LA9_25==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==BY) && ((strict == false))) { + int LA9_26 = input.LA(3); + if ( (LA9_26==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==ASC) && ((strict == false))) { + int LA9_27 = input.LA(3); + if ( (LA9_27==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==DESC) && ((strict == false))) { + int LA9_28 = input.LA(3); + if ( (LA9_28==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==TIMESTAMP) && ((strict == false))) { + int LA9_29 = input.LA(3); + if ( (LA9_29==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==TRUE) && ((strict == false))) { + int LA9_30 = input.LA(3); + if ( (LA9_30==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==FALSE) && ((strict == false))) { + int LA9_31 = input.LA(3); + if ( (LA9_31==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==SCORE) && ((strict == false))) { + int LA9_32 = input.LA(3); + if ( (LA9_32==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + else if ( (LA9_2==ID) && ((strict == false))) { + int LA9_33 = input.LA(3); + if ( (LA9_33==DOUBLE_QUOTE) && ((strict == false))) { + int LA9_34 = input.LA(4); + if ( (LA9_34==DOT) && ((strict == false))) { + alt9=1; + } + } + } + } + switch (alt9) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:354:10: qualifier DOT + { + pushFollow(FOLLOW_qualifier_in_columnReference933); + qualifier18=qualifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_qualifier.add(qualifier18.getTree()); + DOT19=(Token)match(input,DOT,FOLLOW_DOT_in_columnReference935); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DOT.add(DOT19); + + } + break; + + } + + pushFollow(FOLLOW_columnName_in_columnReference939); + columnName20=columnName(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_columnName.add(columnName20.getTree()); + // AST REWRITE + // elements: qualifier, columnName + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 355:17: -> ^( COLUMN_REF columnName ( qualifier )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:356:25: ^( COLUMN_REF columnName ( qualifier )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(COLUMN_REF, "COLUMN_REF"), root_1); + adaptor.addChild(root_1, stream_columnName.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:356:49: ( qualifier )? + if ( stream_qualifier.hasNext() ) { + adaptor.addChild(root_1, stream_qualifier.nextTree()); + } + stream_qualifier.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + if ( state.backtracking==0 ) { + paraphrases.pop(); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "columnReference" + + + public static class valueFunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "valueFunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:359:1: valueFunction : (cmisFunctionName= cmisFunction LPAREN ( functionArgument )* RPAREN -> ^( FUNCTION $cmisFunctionName LPAREN ( functionArgument )* RPAREN ) |{...}? =>functionName= keyWordOrId LPAREN ( functionArgument )* RPAREN -> ^( FUNCTION $functionName LPAREN ( functionArgument )* RPAREN ) ); + public final CMISParser.valueFunction_return valueFunction() throws RecognitionException { + CMISParser.valueFunction_return retval = new CMISParser.valueFunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token LPAREN21=null; + Token RPAREN23=null; + Token LPAREN24=null; + Token RPAREN26=null; + ParserRuleReturnScope cmisFunctionName =null; + ParserRuleReturnScope functionName =null; + ParserRuleReturnScope functionArgument22 =null; + ParserRuleReturnScope functionArgument25 =null; + + Object LPAREN21_tree=null; + Object RPAREN23_tree=null; + Object LPAREN24_tree=null; + Object RPAREN26_tree=null; + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleSubtreeStream stream_cmisFunction=new RewriteRuleSubtreeStream(adaptor,"rule cmisFunction"); + RewriteRuleSubtreeStream stream_keyWordOrId=new RewriteRuleSubtreeStream(adaptor,"rule keyWordOrId"); + RewriteRuleSubtreeStream stream_functionArgument=new RewriteRuleSubtreeStream(adaptor,"rule functionArgument"); + + + paraphrases.push("in function"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:368:9: (cmisFunctionName= cmisFunction LPAREN ( functionArgument )* RPAREN -> ^( FUNCTION $cmisFunctionName LPAREN ( functionArgument )* RPAREN ) |{...}? =>functionName= keyWordOrId LPAREN ( functionArgument )* RPAREN -> ^( FUNCTION $functionName LPAREN ( functionArgument )* RPAREN ) ) + int alt12=2; + alt12 = dfa12.predict(input); + switch (alt12) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:369:9: cmisFunctionName= cmisFunction LPAREN ( functionArgument )* RPAREN + { + pushFollow(FOLLOW_cmisFunction_in_valueFunction1035); + cmisFunctionName=cmisFunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_cmisFunction.add(cmisFunctionName.getTree()); + LPAREN21=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_valueFunction1037); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(LPAREN21); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:369:46: ( functionArgument )* + loop10: + while (true) { + int alt10=2; + int LA10_0 = input.LA(1); + if ( (LA10_0==ID) ) { + alt10=1; + } + else if ( (LA10_0==DOUBLE_QUOTE) && ((strict == false))) { + alt10=1; + } + else if ( (LA10_0==DECIMAL_INTEGER_LITERAL||(LA10_0 >= FALSE && LA10_0 <= FLOATING_POINT_LITERAL)||LA10_0==QUOTED_STRING||(LA10_0 >= TIMESTAMP && LA10_0 <= TRUE)) ) { + alt10=1; + } + else if ( (LA10_0==COLON) && ((strict == false))) { + alt10=1; + } + + switch (alt10) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:369:46: functionArgument + { + pushFollow(FOLLOW_functionArgument_in_valueFunction1039); + functionArgument22=functionArgument(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_functionArgument.add(functionArgument22.getTree()); + } + break; + + default : + break loop10; + } + } + + RPAREN23=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_valueFunction1042); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(RPAREN23); + + // AST REWRITE + // elements: functionArgument, cmisFunctionName, LPAREN, RPAREN + // token labels: + // rule labels: retval, cmisFunctionName + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + RewriteRuleSubtreeStream stream_cmisFunctionName=new RewriteRuleSubtreeStream(adaptor,"rule cmisFunctionName",cmisFunctionName!=null?cmisFunctionName.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 370:17: -> ^( FUNCTION $cmisFunctionName LPAREN ( functionArgument )* RPAREN ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:371:25: ^( FUNCTION $cmisFunctionName LPAREN ( functionArgument )* RPAREN ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FUNCTION, "FUNCTION"), root_1); + adaptor.addChild(root_1, stream_cmisFunctionName.nextTree()); + adaptor.addChild(root_1, stream_LPAREN.nextNode()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:371:61: ( functionArgument )* + while ( stream_functionArgument.hasNext() ) { + adaptor.addChild(root_1, stream_functionArgument.nextTree()); + } + stream_functionArgument.reset(); + + adaptor.addChild(root_1, stream_RPAREN.nextNode()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:372:11: {...}? =>functionName= keyWordOrId LPAREN ( functionArgument )* RPAREN + { + if ( !((strict == false)) ) { + if (state.backtracking>0) {state.failed=true; return retval;} + throw new FailedPredicateException(input, "valueFunction", "strict == false"); + } + pushFollow(FOLLOW_keyWordOrId_in_valueFunction1115); + functionName=keyWordOrId(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_keyWordOrId.add(functionName.getTree()); + LPAREN24=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_valueFunction1117); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(LPAREN24); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:372:64: ( functionArgument )* + loop11: + while (true) { + int alt11=2; + int LA11_0 = input.LA(1); + if ( (LA11_0==ID) ) { + alt11=1; + } + else if ( (LA11_0==DOUBLE_QUOTE) && ((strict == false))) { + alt11=1; + } + else if ( (LA11_0==DECIMAL_INTEGER_LITERAL||(LA11_0 >= FALSE && LA11_0 <= FLOATING_POINT_LITERAL)||LA11_0==QUOTED_STRING||(LA11_0 >= TIMESTAMP && LA11_0 <= TRUE)) ) { + alt11=1; + } + else if ( (LA11_0==COLON) && ((strict == false))) { + alt11=1; + } + + switch (alt11) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:372:64: functionArgument + { + pushFollow(FOLLOW_functionArgument_in_valueFunction1119); + functionArgument25=functionArgument(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_functionArgument.add(functionArgument25.getTree()); + } + break; + + default : + break loop11; + } + } + + RPAREN26=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_valueFunction1122); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(RPAREN26); + + // AST REWRITE + // elements: functionArgument, LPAREN, functionName, RPAREN + // token labels: + // rule labels: retval, functionName + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + RewriteRuleSubtreeStream stream_functionName=new RewriteRuleSubtreeStream(adaptor,"rule functionName",functionName!=null?functionName.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 373:17: -> ^( FUNCTION $functionName LPAREN ( functionArgument )* RPAREN ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:374:25: ^( FUNCTION $functionName LPAREN ( functionArgument )* RPAREN ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FUNCTION, "FUNCTION"), root_1); + adaptor.addChild(root_1, stream_functionName.nextTree()); + adaptor.addChild(root_1, stream_LPAREN.nextNode()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:374:57: ( functionArgument )* + while ( stream_functionArgument.hasNext() ) { + adaptor.addChild(root_1, stream_functionArgument.nextTree()); + } + stream_functionArgument.reset(); + + adaptor.addChild(root_1, stream_RPAREN.nextNode()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + if ( state.backtracking==0 ) { + paraphrases.pop(); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "valueFunction" + + + public static class functionArgument_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "functionArgument" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:377:1: functionArgument : ( qualifier DOT columnName -> ^( COLUMN_REF columnName qualifier ) | identifier | literalOrParameterName ); + public final CMISParser.functionArgument_return functionArgument() throws RecognitionException { + CMISParser.functionArgument_return retval = new CMISParser.functionArgument_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token DOT28=null; + ParserRuleReturnScope qualifier27 =null; + ParserRuleReturnScope columnName29 =null; + ParserRuleReturnScope identifier30 =null; + ParserRuleReturnScope literalOrParameterName31 =null; + + Object DOT28_tree=null; + RewriteRuleTokenStream stream_DOT=new RewriteRuleTokenStream(adaptor,"token DOT"); + RewriteRuleSubtreeStream stream_columnName=new RewriteRuleSubtreeStream(adaptor,"rule columnName"); + RewriteRuleSubtreeStream stream_qualifier=new RewriteRuleSubtreeStream(adaptor,"rule qualifier"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:378:9: ( qualifier DOT columnName -> ^( COLUMN_REF columnName qualifier ) | identifier | literalOrParameterName ) + int alt13=3; + int LA13_0 = input.LA(1); + if ( (LA13_0==ID) ) { + int LA13_1 = input.LA(2); + if ( (LA13_1==DOT) ) { + alt13=1; + } + else if ( (LA13_1==COLON||LA13_1==DECIMAL_INTEGER_LITERAL||LA13_1==DOUBLE_QUOTE||(LA13_1 >= FALSE && LA13_1 <= FLOATING_POINT_LITERAL)||LA13_1==ID||(LA13_1 >= QUOTED_STRING && LA13_1 <= RPAREN)||(LA13_1 >= TIMESTAMP && LA13_1 <= TRUE)) ) { + alt13=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 13, 1, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + else if ( (LA13_0==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_2 = input.LA(2); + if ( (LA13_2==SELECT) && ((strict == false))) { + int LA13_7 = input.LA(3); + if ( (LA13_7==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==AS) && ((strict == false))) { + int LA13_8 = input.LA(3); + if ( (LA13_8==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==FROM) && ((strict == false))) { + int LA13_9 = input.LA(3); + if ( (LA13_9==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==JOIN) && ((strict == false))) { + int LA13_10 = input.LA(3); + if ( (LA13_10==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==INNER) && ((strict == false))) { + int LA13_11 = input.LA(3); + if ( (LA13_11==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==LEFT) && ((strict == false))) { + int LA13_12 = input.LA(3); + if ( (LA13_12==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==OUTER) && ((strict == false))) { + int LA13_13 = input.LA(3); + if ( (LA13_13==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==ON) && ((strict == false))) { + int LA13_14 = input.LA(3); + if ( (LA13_14==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==WHERE) && ((strict == false))) { + int LA13_15 = input.LA(3); + if ( (LA13_15==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==OR) && ((strict == false))) { + int LA13_16 = input.LA(3); + if ( (LA13_16==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==AND) && ((strict == false))) { + int LA13_17 = input.LA(3); + if ( (LA13_17==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==NOT) && ((strict == false))) { + int LA13_18 = input.LA(3); + if ( (LA13_18==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==IN) && ((strict == false))) { + int LA13_19 = input.LA(3); + if ( (LA13_19==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==LIKE) && ((strict == false))) { + int LA13_20 = input.LA(3); + if ( (LA13_20==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==IS) && ((strict == false))) { + int LA13_21 = input.LA(3); + if ( (LA13_21==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==NULL) && ((strict == false))) { + int LA13_22 = input.LA(3); + if ( (LA13_22==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==ANY) && ((strict == false))) { + int LA13_23 = input.LA(3); + if ( (LA13_23==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==CONTAINS) && ((strict == false))) { + int LA13_24 = input.LA(3); + if ( (LA13_24==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==IN_FOLDER) && ((strict == false))) { + int LA13_25 = input.LA(3); + if ( (LA13_25==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==IN_TREE) && ((strict == false))) { + int LA13_26 = input.LA(3); + if ( (LA13_26==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==ORDER) && ((strict == false))) { + int LA13_27 = input.LA(3); + if ( (LA13_27==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==BY) && ((strict == false))) { + int LA13_28 = input.LA(3); + if ( (LA13_28==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==ASC) && ((strict == false))) { + int LA13_29 = input.LA(3); + if ( (LA13_29==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==DESC) && ((strict == false))) { + int LA13_30 = input.LA(3); + if ( (LA13_30==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==TIMESTAMP) && ((strict == false))) { + int LA13_31 = input.LA(3); + if ( (LA13_31==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==TRUE) && ((strict == false))) { + int LA13_32 = input.LA(3); + if ( (LA13_32==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==FALSE) && ((strict == false))) { + int LA13_33 = input.LA(3); + if ( (LA13_33==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==SCORE) && ((strict == false))) { + int LA13_34 = input.LA(3); + if ( (LA13_34==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + else if ( (LA13_2==ID) && ((strict == false))) { + int LA13_35 = input.LA(3); + if ( (LA13_35==DOUBLE_QUOTE) && ((strict == false))) { + int LA13_36 = input.LA(4); + if ( (LA13_36==DOT) && ((strict == false))) { + alt13=1; + } + else if ( (LA13_36==COLON||LA13_36==DECIMAL_INTEGER_LITERAL||LA13_36==DOUBLE_QUOTE||(LA13_36 >= FALSE && LA13_36 <= FLOATING_POINT_LITERAL)||LA13_36==ID||(LA13_36 >= QUOTED_STRING && LA13_36 <= RPAREN)||(LA13_36 >= TIMESTAMP && LA13_36 <= TRUE)) && ((strict == false))) { + alt13=2; + } + + } + + } + + } + else if ( (LA13_0==DECIMAL_INTEGER_LITERAL||(LA13_0 >= FALSE && LA13_0 <= FLOATING_POINT_LITERAL)||LA13_0==QUOTED_STRING||(LA13_0 >= TIMESTAMP && LA13_0 <= TRUE)) ) { + alt13=3; + } + else if ( (LA13_0==COLON) && ((strict == false))) { + alt13=3; + } + + switch (alt13) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:379:9: qualifier DOT columnName + { + pushFollow(FOLLOW_qualifier_in_functionArgument1211); + qualifier27=qualifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_qualifier.add(qualifier27.getTree()); + DOT28=(Token)match(input,DOT,FOLLOW_DOT_in_functionArgument1213); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DOT.add(DOT28); + + pushFollow(FOLLOW_columnName_in_functionArgument1215); + columnName29=columnName(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_columnName.add(columnName29.getTree()); + // AST REWRITE + // elements: columnName, qualifier + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 380:17: -> ^( COLUMN_REF columnName qualifier ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:381:25: ^( COLUMN_REF columnName qualifier ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(COLUMN_REF, "COLUMN_REF"), root_1); + adaptor.addChild(root_1, stream_columnName.nextTree()); + adaptor.addChild(root_1, stream_qualifier.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:382:11: identifier + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_identifier_in_functionArgument1277); + identifier30=identifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, identifier30.getTree()); + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:383:11: literalOrParameterName + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_literalOrParameterName_in_functionArgument1289); + literalOrParameterName31=literalOrParameterName(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, literalOrParameterName31.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "functionArgument" + + + public static class qualifier_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "qualifier" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:386:1: qualifier : ( ( tableName )=> tableName -> tableName | correlationName -> correlationName ); + public final CMISParser.qualifier_return qualifier() throws RecognitionException { + CMISParser.qualifier_return retval = new CMISParser.qualifier_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope tableName32 =null; + ParserRuleReturnScope correlationName33 =null; + + RewriteRuleSubtreeStream stream_correlationName=new RewriteRuleSubtreeStream(adaptor,"rule correlationName"); + RewriteRuleSubtreeStream stream_tableName=new RewriteRuleSubtreeStream(adaptor,"rule tableName"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:387:9: ( ( tableName )=> tableName -> tableName | correlationName -> correlationName ) + int alt14=2; + int LA14_0 = input.LA(1); + if ( (LA14_0==ID) ) { + int LA14_1 = input.LA(2); + if ( (synpred1_CMIS()) ) { + alt14=1; + } + else if ( (true) ) { + alt14=2; + } + + } + else if ( (LA14_0==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_2 = input.LA(2); + if ( (LA14_2==SELECT) && ((strict == false))) { + int LA14_5 = input.LA(3); + if ( (LA14_5==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==AS) && ((strict == false))) { + int LA14_6 = input.LA(3); + if ( (LA14_6==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==FROM) && ((strict == false))) { + int LA14_7 = input.LA(3); + if ( (LA14_7==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==JOIN) && ((strict == false))) { + int LA14_8 = input.LA(3); + if ( (LA14_8==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==INNER) && ((strict == false))) { + int LA14_9 = input.LA(3); + if ( (LA14_9==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==LEFT) && ((strict == false))) { + int LA14_10 = input.LA(3); + if ( (LA14_10==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==OUTER) && ((strict == false))) { + int LA14_11 = input.LA(3); + if ( (LA14_11==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==ON) && ((strict == false))) { + int LA14_12 = input.LA(3); + if ( (LA14_12==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==WHERE) && ((strict == false))) { + int LA14_13 = input.LA(3); + if ( (LA14_13==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==OR) && ((strict == false))) { + int LA14_14 = input.LA(3); + if ( (LA14_14==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==AND) && ((strict == false))) { + int LA14_15 = input.LA(3); + if ( (LA14_15==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==NOT) && ((strict == false))) { + int LA14_16 = input.LA(3); + if ( (LA14_16==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==IN) && ((strict == false))) { + int LA14_17 = input.LA(3); + if ( (LA14_17==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==LIKE) && ((strict == false))) { + int LA14_18 = input.LA(3); + if ( (LA14_18==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==IS) && ((strict == false))) { + int LA14_19 = input.LA(3); + if ( (LA14_19==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==NULL) && ((strict == false))) { + int LA14_20 = input.LA(3); + if ( (LA14_20==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==ANY) && ((strict == false))) { + int LA14_21 = input.LA(3); + if ( (LA14_21==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==CONTAINS) && ((strict == false))) { + int LA14_22 = input.LA(3); + if ( (LA14_22==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==IN_FOLDER) && ((strict == false))) { + int LA14_23 = input.LA(3); + if ( (LA14_23==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==IN_TREE) && ((strict == false))) { + int LA14_24 = input.LA(3); + if ( (LA14_24==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==ORDER) && ((strict == false))) { + int LA14_25 = input.LA(3); + if ( (LA14_25==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==BY) && ((strict == false))) { + int LA14_26 = input.LA(3); + if ( (LA14_26==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==ASC) && ((strict == false))) { + int LA14_27 = input.LA(3); + if ( (LA14_27==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==DESC) && ((strict == false))) { + int LA14_28 = input.LA(3); + if ( (LA14_28==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==TIMESTAMP) && ((strict == false))) { + int LA14_29 = input.LA(3); + if ( (LA14_29==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==TRUE) && ((strict == false))) { + int LA14_30 = input.LA(3); + if ( (LA14_30==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==FALSE) && ((strict == false))) { + int LA14_31 = input.LA(3); + if ( (LA14_31==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==SCORE) && ((strict == false))) { + int LA14_32 = input.LA(3); + if ( (LA14_32==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + else if ( (LA14_2==ID) && ((strict == false))) { + int LA14_33 = input.LA(3); + if ( (LA14_33==DOUBLE_QUOTE) && ((strict == false))) { + int LA14_34 = input.LA(4); + if ( (((strict == false)&&synpred1_CMIS())) ) { + alt14=1; + } + else if ( ((strict == false)) ) { + alt14=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 14, 34, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + } + + } + + switch (alt14) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:388:9: ( tableName )=> tableName + { + pushFollow(FOLLOW_tableName_in_qualifier1328); + tableName32=tableName(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_tableName.add(tableName32.getTree()); + // AST REWRITE + // elements: tableName + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 389:17: -> tableName + { + adaptor.addChild(root_0, stream_tableName.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:390:11: correlationName + { + pushFollow(FOLLOW_correlationName_in_qualifier1360); + correlationName33=correlationName(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_correlationName.add(correlationName33.getTree()); + // AST REWRITE + // elements: correlationName + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 391:17: -> correlationName + { + adaptor.addChild(root_0, stream_correlationName.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "qualifier" + + + public static class fromClause_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "fromClause" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:394:1: fromClause : FROM tableReference -> tableReference ; + public final CMISParser.fromClause_return fromClause() throws RecognitionException { + CMISParser.fromClause_return retval = new CMISParser.fromClause_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token FROM34=null; + ParserRuleReturnScope tableReference35 =null; + + Object FROM34_tree=null; + RewriteRuleTokenStream stream_FROM=new RewriteRuleTokenStream(adaptor,"token FROM"); + RewriteRuleSubtreeStream stream_tableReference=new RewriteRuleSubtreeStream(adaptor,"rule tableReference"); + + + paraphrases.push("in fromClause"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:403:9: ( FROM tableReference -> tableReference ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:404:9: FROM tableReference + { + FROM34=(Token)match(input,FROM,FOLLOW_FROM_in_fromClause1423); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_FROM.add(FROM34); + + pushFollow(FOLLOW_tableReference_in_fromClause1425); + tableReference35=tableReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_tableReference.add(tableReference35.getTree()); + // AST REWRITE + // elements: tableReference + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 405:17: -> tableReference + { + adaptor.addChild(root_0, stream_tableReference.nextTree()); + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + if ( state.backtracking==0 ) { + paraphrases.pop(); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "fromClause" + + + public static class tableReference_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "tableReference" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:408:1: tableReference : singleTable ( joinedTable )* -> ^( SOURCE singleTable ( joinedTable )* ) ; + public final CMISParser.tableReference_return tableReference() throws RecognitionException { + CMISParser.tableReference_return retval = new CMISParser.tableReference_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope singleTable36 =null; + ParserRuleReturnScope joinedTable37 =null; + + RewriteRuleSubtreeStream stream_singleTable=new RewriteRuleSubtreeStream(adaptor,"rule singleTable"); + RewriteRuleSubtreeStream stream_joinedTable=new RewriteRuleSubtreeStream(adaptor,"rule joinedTable"); + + + paraphrases.push("in tableReference"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:417:9: ( singleTable ( joinedTable )* -> ^( SOURCE singleTable ( joinedTable )* ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:418:9: singleTable ( joinedTable )* + { + pushFollow(FOLLOW_singleTable_in_tableReference1488); + singleTable36=singleTable(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_singleTable.add(singleTable36.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:418:21: ( joinedTable )* + loop15: + while (true) { + int alt15=2; + int LA15_0 = input.LA(1); + if ( (LA15_0==INNER||(LA15_0 >= JOIN && LA15_0 <= LEFT)) ) { + alt15=1; + } + + switch (alt15) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:418:21: joinedTable + { + pushFollow(FOLLOW_joinedTable_in_tableReference1490); + joinedTable37=joinedTable(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_joinedTable.add(joinedTable37.getTree()); + } + break; + + default : + break loop15; + } + } + + // AST REWRITE + // elements: singleTable, joinedTable + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 419:17: -> ^( SOURCE singleTable ( joinedTable )* ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:420:25: ^( SOURCE singleTable ( joinedTable )* ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(SOURCE, "SOURCE"), root_1); + adaptor.addChild(root_1, stream_singleTable.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:420:46: ( joinedTable )* + while ( stream_joinedTable.hasNext() ) { + adaptor.addChild(root_1, stream_joinedTable.nextTree()); + } + stream_joinedTable.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + if ( state.backtracking==0 ) { + paraphrases.pop(); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "tableReference" + + + public static class singleTable_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "singleTable" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:427:1: singleTable : ( simpleTable -> simpleTable | complexTable -> ^( TABLE complexTable ) ); + public final CMISParser.singleTable_return singleTable() throws RecognitionException { + CMISParser.singleTable_return retval = new CMISParser.singleTable_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope simpleTable38 =null; + ParserRuleReturnScope complexTable39 =null; + + RewriteRuleSubtreeStream stream_simpleTable=new RewriteRuleSubtreeStream(adaptor,"rule simpleTable"); + RewriteRuleSubtreeStream stream_complexTable=new RewriteRuleSubtreeStream(adaptor,"rule complexTable"); + + + paraphrases.push("in singleTable"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:436:9: ( simpleTable -> simpleTable | complexTable -> ^( TABLE complexTable ) ) + int alt16=2; + int LA16_0 = input.LA(1); + if ( (LA16_0==ID) ) { + alt16=1; + } + else if ( (LA16_0==DOUBLE_QUOTE) && ((strict == false))) { + alt16=1; + } + else if ( (LA16_0==LPAREN) ) { + alt16=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 16, 0, input); + throw nvae; + } + + switch (alt16) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:437:9: simpleTable + { + pushFollow(FOLLOW_simpleTable_in_singleTable1588); + simpleTable38=simpleTable(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_simpleTable.add(simpleTable38.getTree()); + // AST REWRITE + // elements: simpleTable + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 438:17: -> simpleTable + { + adaptor.addChild(root_0, stream_simpleTable.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:439:11: complexTable + { + pushFollow(FOLLOW_complexTable_in_singleTable1620); + complexTable39=complexTable(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_complexTable.add(complexTable39.getTree()); + // AST REWRITE + // elements: complexTable + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 440:17: -> ^( TABLE complexTable ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:441:25: ^( TABLE complexTable ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(TABLE, "TABLE"), root_1); + adaptor.addChild(root_1, stream_complexTable.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + if ( state.backtracking==0 ) { + paraphrases.pop(); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "singleTable" + + + public static class simpleTable_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "simpleTable" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:444:1: simpleTable : tableName ( ( AS )? correlationName )? -> ^( TABLE_REF tableName ( correlationName )? ) ; + public final CMISParser.simpleTable_return simpleTable() throws RecognitionException { + CMISParser.simpleTable_return retval = new CMISParser.simpleTable_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token AS41=null; + ParserRuleReturnScope tableName40 =null; + ParserRuleReturnScope correlationName42 =null; + + Object AS41_tree=null; + RewriteRuleTokenStream stream_AS=new RewriteRuleTokenStream(adaptor,"token AS"); + RewriteRuleSubtreeStream stream_correlationName=new RewriteRuleSubtreeStream(adaptor,"rule correlationName"); + RewriteRuleSubtreeStream stream_tableName=new RewriteRuleSubtreeStream(adaptor,"rule tableName"); + + + paraphrases.push("in simpleTable"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:453:9: ( tableName ( ( AS )? correlationName )? -> ^( TABLE_REF tableName ( correlationName )? ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:454:9: tableName ( ( AS )? correlationName )? + { + pushFollow(FOLLOW_tableName_in_simpleTable1711); + tableName40=tableName(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_tableName.add(tableName40.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:454:19: ( ( AS )? correlationName )? + int alt18=2; + int LA18_0 = input.LA(1); + if ( (LA18_0==AS||LA18_0==ID) ) { + alt18=1; + } + else if ( (LA18_0==DOUBLE_QUOTE) && ((strict == false))) { + alt18=1; + } + switch (alt18) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:454:20: ( AS )? correlationName + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:454:20: ( AS )? + int alt17=2; + int LA17_0 = input.LA(1); + if ( (LA17_0==AS) ) { + alt17=1; + } + switch (alt17) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:454:20: AS + { + AS41=(Token)match(input,AS,FOLLOW_AS_in_simpleTable1714); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_AS.add(AS41); + + } + break; + + } + + pushFollow(FOLLOW_correlationName_in_simpleTable1717); + correlationName42=correlationName(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_correlationName.add(correlationName42.getTree()); + } + break; + + } + + // AST REWRITE + // elements: correlationName, tableName + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 455:17: -> ^( TABLE_REF tableName ( correlationName )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:456:25: ^( TABLE_REF tableName ( correlationName )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(TABLE_REF, "TABLE_REF"), root_1); + adaptor.addChild(root_1, stream_tableName.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:456:47: ( correlationName )? + if ( stream_correlationName.hasNext() ) { + adaptor.addChild(root_1, stream_correlationName.nextTree()); + } + stream_correlationName.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + if ( state.backtracking==0 ) { + paraphrases.pop(); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "simpleTable" + + + public static class joinedTable_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "joinedTable" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:459:1: joinedTable : ( joinType )? JOIN tableReference joinSpecification -> ^( JOIN tableReference ( joinType )? joinSpecification ) ; + public final CMISParser.joinedTable_return joinedTable() throws RecognitionException { + CMISParser.joinedTable_return retval = new CMISParser.joinedTable_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token JOIN44=null; + ParserRuleReturnScope joinType43 =null; + ParserRuleReturnScope tableReference45 =null; + ParserRuleReturnScope joinSpecification46 =null; + + Object JOIN44_tree=null; + RewriteRuleTokenStream stream_JOIN=new RewriteRuleTokenStream(adaptor,"token JOIN"); + RewriteRuleSubtreeStream stream_tableReference=new RewriteRuleSubtreeStream(adaptor,"rule tableReference"); + RewriteRuleSubtreeStream stream_joinType=new RewriteRuleSubtreeStream(adaptor,"rule joinType"); + RewriteRuleSubtreeStream stream_joinSpecification=new RewriteRuleSubtreeStream(adaptor,"rule joinSpecification"); + + + paraphrases.push("in joinedTable"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:468:9: ( ( joinType )? JOIN tableReference joinSpecification -> ^( JOIN tableReference ( joinType )? joinSpecification ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:469:9: ( joinType )? JOIN tableReference joinSpecification + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:469:9: ( joinType )? + int alt19=2; + int LA19_0 = input.LA(1); + if ( (LA19_0==INNER||LA19_0==LEFT) ) { + alt19=1; + } + switch (alt19) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:469:9: joinType + { + pushFollow(FOLLOW_joinType_in_joinedTable1813); + joinType43=joinType(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_joinType.add(joinType43.getTree()); + } + break; + + } + + JOIN44=(Token)match(input,JOIN,FOLLOW_JOIN_in_joinedTable1816); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_JOIN.add(JOIN44); + + pushFollow(FOLLOW_tableReference_in_joinedTable1818); + tableReference45=tableReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_tableReference.add(tableReference45.getTree()); + pushFollow(FOLLOW_joinSpecification_in_joinedTable1820); + joinSpecification46=joinSpecification(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_joinSpecification.add(joinSpecification46.getTree()); + // AST REWRITE + // elements: joinType, JOIN, tableReference, joinSpecification + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 470:17: -> ^( JOIN tableReference ( joinType )? joinSpecification ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:471:25: ^( JOIN tableReference ( joinType )? joinSpecification ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(stream_JOIN.nextNode(), root_1); + adaptor.addChild(root_1, stream_tableReference.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:471:47: ( joinType )? + if ( stream_joinType.hasNext() ) { + adaptor.addChild(root_1, stream_joinType.nextTree()); + } + stream_joinType.reset(); + + adaptor.addChild(root_1, stream_joinSpecification.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + if ( state.backtracking==0 ) { + paraphrases.pop(); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "joinedTable" + + + public static class complexTable_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "complexTable" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:474:1: complexTable : ( ( LPAREN singleTable ( joinedTable )+ RPAREN )=> LPAREN singleTable ( joinedTable )+ RPAREN -> ^( SOURCE singleTable ( joinedTable )+ ) | LPAREN complexTable RPAREN -> complexTable ); + public final CMISParser.complexTable_return complexTable() throws RecognitionException { + CMISParser.complexTable_return retval = new CMISParser.complexTable_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token LPAREN47=null; + Token RPAREN50=null; + Token LPAREN51=null; + Token RPAREN53=null; + ParserRuleReturnScope singleTable48 =null; + ParserRuleReturnScope joinedTable49 =null; + ParserRuleReturnScope complexTable52 =null; + + Object LPAREN47_tree=null; + Object RPAREN50_tree=null; + Object LPAREN51_tree=null; + Object RPAREN53_tree=null; + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleSubtreeStream stream_singleTable=new RewriteRuleSubtreeStream(adaptor,"rule singleTable"); + RewriteRuleSubtreeStream stream_joinedTable=new RewriteRuleSubtreeStream(adaptor,"rule joinedTable"); + RewriteRuleSubtreeStream stream_complexTable=new RewriteRuleSubtreeStream(adaptor,"rule complexTable"); + + + paraphrases.push("in complexTable"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:483:9: ( ( LPAREN singleTable ( joinedTable )+ RPAREN )=> LPAREN singleTable ( joinedTable )+ RPAREN -> ^( SOURCE singleTable ( joinedTable )+ ) | LPAREN complexTable RPAREN -> complexTable ) + int alt21=2; + int LA21_0 = input.LA(1); + if ( (LA21_0==LPAREN) ) { + int LA21_1 = input.LA(2); + if ( (synpred2_CMIS()) ) { + alt21=1; + } + else if ( (true) ) { + alt21=2; + } + + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 21, 0, input); + throw nvae; + } + + switch (alt21) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:484:9: ( LPAREN singleTable ( joinedTable )+ RPAREN )=> LPAREN singleTable ( joinedTable )+ RPAREN + { + LPAREN47=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_complexTable1929); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(LPAREN47); + + pushFollow(FOLLOW_singleTable_in_complexTable1931); + singleTable48=singleTable(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_singleTable.add(singleTable48.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:484:72: ( joinedTable )+ + int cnt20=0; + loop20: + while (true) { + int alt20=2; + int LA20_0 = input.LA(1); + if ( (LA20_0==INNER||(LA20_0 >= JOIN && LA20_0 <= LEFT)) ) { + alt20=1; + } + + switch (alt20) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:484:72: joinedTable + { + pushFollow(FOLLOW_joinedTable_in_complexTable1933); + joinedTable49=joinedTable(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_joinedTable.add(joinedTable49.getTree()); + } + break; + + default : + if ( cnt20 >= 1 ) break loop20; + if (state.backtracking>0) {state.failed=true; return retval;} + EarlyExitException eee = new EarlyExitException(20, input); + throw eee; + } + cnt20++; + } + + RPAREN50=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_complexTable1936); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(RPAREN50); + + // AST REWRITE + // elements: joinedTable, singleTable + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 485:17: -> ^( SOURCE singleTable ( joinedTable )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:486:25: ^( SOURCE singleTable ( joinedTable )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(SOURCE, "SOURCE"), root_1); + adaptor.addChild(root_1, stream_singleTable.nextTree()); + if ( !(stream_joinedTable.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_joinedTable.hasNext() ) { + adaptor.addChild(root_1, stream_joinedTable.nextTree()); + } + stream_joinedTable.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:487:11: LPAREN complexTable RPAREN + { + LPAREN51=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_complexTable1999); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(LPAREN51); + + pushFollow(FOLLOW_complexTable_in_complexTable2001); + complexTable52=complexTable(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_complexTable.add(complexTable52.getTree()); + RPAREN53=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_complexTable2003); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(RPAREN53); + + // AST REWRITE + // elements: complexTable + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 488:17: -> complexTable + { + adaptor.addChild(root_0, stream_complexTable.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + if ( state.backtracking==0 ) { + paraphrases.pop(); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "complexTable" + + + public static class joinType_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "joinType" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:491:1: joinType : ( INNER -> INNER | LEFT ( OUTER )? -> LEFT ); + public final CMISParser.joinType_return joinType() throws RecognitionException { + CMISParser.joinType_return retval = new CMISParser.joinType_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token INNER54=null; + Token LEFT55=null; + Token OUTER56=null; + + Object INNER54_tree=null; + Object LEFT55_tree=null; + Object OUTER56_tree=null; + RewriteRuleTokenStream stream_OUTER=new RewriteRuleTokenStream(adaptor,"token OUTER"); + RewriteRuleTokenStream stream_INNER=new RewriteRuleTokenStream(adaptor,"token INNER"); + RewriteRuleTokenStream stream_LEFT=new RewriteRuleTokenStream(adaptor,"token LEFT"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:492:9: ( INNER -> INNER | LEFT ( OUTER )? -> LEFT ) + int alt23=2; + int LA23_0 = input.LA(1); + if ( (LA23_0==INNER) ) { + alt23=1; + } + else if ( (LA23_0==LEFT) ) { + alt23=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 23, 0, input); + throw nvae; + } + + switch (alt23) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:493:9: INNER + { + INNER54=(Token)match(input,INNER,FOLLOW_INNER_in_joinType2056); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_INNER.add(INNER54); + + // AST REWRITE + // elements: INNER + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 494:17: -> INNER + { + adaptor.addChild(root_0, stream_INNER.nextNode()); + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:495:11: LEFT ( OUTER )? + { + LEFT55=(Token)match(input,LEFT,FOLLOW_LEFT_in_joinType2088); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LEFT.add(LEFT55); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:495:16: ( OUTER )? + int alt22=2; + int LA22_0 = input.LA(1); + if ( (LA22_0==OUTER) ) { + alt22=1; + } + switch (alt22) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:495:16: OUTER + { + OUTER56=(Token)match(input,OUTER,FOLLOW_OUTER_in_joinType2090); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_OUTER.add(OUTER56); + + } + break; + + } + + // AST REWRITE + // elements: LEFT + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 496:17: -> LEFT + { + adaptor.addChild(root_0, stream_LEFT.nextNode()); + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "joinType" + + + public static class joinSpecification_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "joinSpecification" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:499:1: joinSpecification : ON lhs= columnReference EQUALS rhs= columnReference -> ^( ON $lhs EQUALS $rhs) ; + public final CMISParser.joinSpecification_return joinSpecification() throws RecognitionException { + CMISParser.joinSpecification_return retval = new CMISParser.joinSpecification_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token ON57=null; + Token EQUALS58=null; + ParserRuleReturnScope lhs =null; + ParserRuleReturnScope rhs =null; + + Object ON57_tree=null; + Object EQUALS58_tree=null; + RewriteRuleTokenStream stream_ON=new RewriteRuleTokenStream(adaptor,"token ON"); + RewriteRuleTokenStream stream_EQUALS=new RewriteRuleTokenStream(adaptor,"token EQUALS"); + RewriteRuleSubtreeStream stream_columnReference=new RewriteRuleSubtreeStream(adaptor,"rule columnReference"); + + + paraphrases.push("in join condition"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:508:9: ( ON lhs= columnReference EQUALS rhs= columnReference -> ^( ON $lhs EQUALS $rhs) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:509:9: ON lhs= columnReference EQUALS rhs= columnReference + { + ON57=(Token)match(input,ON,FOLLOW_ON_in_joinSpecification2154); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ON.add(ON57); + + pushFollow(FOLLOW_columnReference_in_joinSpecification2158); + lhs=columnReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_columnReference.add(lhs.getTree()); + EQUALS58=(Token)match(input,EQUALS,FOLLOW_EQUALS_in_joinSpecification2160); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_EQUALS.add(EQUALS58); + + pushFollow(FOLLOW_columnReference_in_joinSpecification2164); + rhs=columnReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_columnReference.add(rhs.getTree()); + // AST REWRITE + // elements: ON, EQUALS, rhs, lhs + // token labels: + // rule labels: retval, rhs, lhs + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + RewriteRuleSubtreeStream stream_rhs=new RewriteRuleSubtreeStream(adaptor,"rule rhs",rhs!=null?rhs.getTree():null); + RewriteRuleSubtreeStream stream_lhs=new RewriteRuleSubtreeStream(adaptor,"rule lhs",lhs!=null?lhs.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 510:17: -> ^( ON $lhs EQUALS $rhs) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:511:25: ^( ON $lhs EQUALS $rhs) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(stream_ON.nextNode(), root_1); + adaptor.addChild(root_1, stream_lhs.nextTree()); + adaptor.addChild(root_1, stream_EQUALS.nextNode()); + adaptor.addChild(root_1, stream_rhs.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + if ( state.backtracking==0 ) { + paraphrases.pop(); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "joinSpecification" + + + public static class whereClause_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "whereClause" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:518:1: whereClause : WHERE searchOrCondition -> searchOrCondition ; + public final CMISParser.whereClause_return whereClause() throws RecognitionException { + CMISParser.whereClause_return retval = new CMISParser.whereClause_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token WHERE59=null; + ParserRuleReturnScope searchOrCondition60 =null; + + Object WHERE59_tree=null; + RewriteRuleTokenStream stream_WHERE=new RewriteRuleTokenStream(adaptor,"token WHERE"); + RewriteRuleSubtreeStream stream_searchOrCondition=new RewriteRuleSubtreeStream(adaptor,"rule searchOrCondition"); + + + paraphrases.push("in where"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:527:9: ( WHERE searchOrCondition -> searchOrCondition ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:528:9: WHERE searchOrCondition + { + WHERE59=(Token)match(input,WHERE,FOLLOW_WHERE_in_whereClause2264); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_WHERE.add(WHERE59); + + pushFollow(FOLLOW_searchOrCondition_in_whereClause2266); + searchOrCondition60=searchOrCondition(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_searchOrCondition.add(searchOrCondition60.getTree()); + // AST REWRITE + // elements: searchOrCondition + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 529:17: -> searchOrCondition + { + adaptor.addChild(root_0, stream_searchOrCondition.nextTree()); + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + if ( state.backtracking==0 ) { + paraphrases.pop(); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "whereClause" + + + public static class searchOrCondition_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "searchOrCondition" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:535:1: searchOrCondition : searchAndCondition ( OR searchAndCondition )* -> ^( DISJUNCTION ( searchAndCondition )+ ) ; + public final CMISParser.searchOrCondition_return searchOrCondition() throws RecognitionException { + CMISParser.searchOrCondition_return retval = new CMISParser.searchOrCondition_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token OR62=null; + ParserRuleReturnScope searchAndCondition61 =null; + ParserRuleReturnScope searchAndCondition63 =null; + + Object OR62_tree=null; + RewriteRuleTokenStream stream_OR=new RewriteRuleTokenStream(adaptor,"token OR"); + RewriteRuleSubtreeStream stream_searchAndCondition=new RewriteRuleSubtreeStream(adaptor,"rule searchAndCondition"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:536:9: ( searchAndCondition ( OR searchAndCondition )* -> ^( DISJUNCTION ( searchAndCondition )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:537:9: searchAndCondition ( OR searchAndCondition )* + { + pushFollow(FOLLOW_searchAndCondition_in_searchOrCondition2321); + searchAndCondition61=searchAndCondition(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_searchAndCondition.add(searchAndCondition61.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:537:28: ( OR searchAndCondition )* + loop24: + while (true) { + int alt24=2; + int LA24_0 = input.LA(1); + if ( (LA24_0==OR) ) { + alt24=1; + } + + switch (alt24) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:537:29: OR searchAndCondition + { + OR62=(Token)match(input,OR,FOLLOW_OR_in_searchOrCondition2324); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_OR.add(OR62); + + pushFollow(FOLLOW_searchAndCondition_in_searchOrCondition2326); + searchAndCondition63=searchAndCondition(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_searchAndCondition.add(searchAndCondition63.getTree()); + } + break; + + default : + break loop24; + } + } + + // AST REWRITE + // elements: searchAndCondition + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 538:17: -> ^( DISJUNCTION ( searchAndCondition )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:539:25: ^( DISJUNCTION ( searchAndCondition )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(DISJUNCTION, "DISJUNCTION"), root_1); + if ( !(stream_searchAndCondition.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_searchAndCondition.hasNext() ) { + adaptor.addChild(root_1, stream_searchAndCondition.nextTree()); + } + stream_searchAndCondition.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "searchOrCondition" + + + public static class searchAndCondition_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "searchAndCondition" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:545:1: searchAndCondition : searchNotCondition ( AND searchNotCondition )* -> ^( CONJUNCTION ( searchNotCondition )+ ) ; + public final CMISParser.searchAndCondition_return searchAndCondition() throws RecognitionException { + CMISParser.searchAndCondition_return retval = new CMISParser.searchAndCondition_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token AND65=null; + ParserRuleReturnScope searchNotCondition64 =null; + ParserRuleReturnScope searchNotCondition66 =null; + + Object AND65_tree=null; + RewriteRuleTokenStream stream_AND=new RewriteRuleTokenStream(adaptor,"token AND"); + RewriteRuleSubtreeStream stream_searchNotCondition=new RewriteRuleSubtreeStream(adaptor,"rule searchNotCondition"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:546:9: ( searchNotCondition ( AND searchNotCondition )* -> ^( CONJUNCTION ( searchNotCondition )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:547:9: searchNotCondition ( AND searchNotCondition )* + { + pushFollow(FOLLOW_searchNotCondition_in_searchAndCondition2412); + searchNotCondition64=searchNotCondition(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_searchNotCondition.add(searchNotCondition64.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:547:28: ( AND searchNotCondition )* + loop25: + while (true) { + int alt25=2; + int LA25_0 = input.LA(1); + if ( (LA25_0==AND) ) { + alt25=1; + } + + switch (alt25) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:547:29: AND searchNotCondition + { + AND65=(Token)match(input,AND,FOLLOW_AND_in_searchAndCondition2415); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_AND.add(AND65); + + pushFollow(FOLLOW_searchNotCondition_in_searchAndCondition2417); + searchNotCondition66=searchNotCondition(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_searchNotCondition.add(searchNotCondition66.getTree()); + } + break; + + default : + break loop25; + } + } + + // AST REWRITE + // elements: searchNotCondition + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 548:17: -> ^( CONJUNCTION ( searchNotCondition )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:549:25: ^( CONJUNCTION ( searchNotCondition )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(CONJUNCTION, "CONJUNCTION"), root_1); + if ( !(stream_searchNotCondition.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_searchNotCondition.hasNext() ) { + adaptor.addChild(root_1, stream_searchNotCondition.nextTree()); + } + stream_searchNotCondition.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "searchAndCondition" + + + public static class searchNotCondition_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "searchNotCondition" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:552:1: searchNotCondition : ( NOT searchTest -> ^( NEGATION searchTest ) | searchTest -> searchTest ); + public final CMISParser.searchNotCondition_return searchNotCondition() throws RecognitionException { + CMISParser.searchNotCondition_return retval = new CMISParser.searchNotCondition_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token NOT67=null; + ParserRuleReturnScope searchTest68 =null; + ParserRuleReturnScope searchTest69 =null; + + Object NOT67_tree=null; + RewriteRuleTokenStream stream_NOT=new RewriteRuleTokenStream(adaptor,"token NOT"); + RewriteRuleSubtreeStream stream_searchTest=new RewriteRuleSubtreeStream(adaptor,"rule searchTest"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:553:9: ( NOT searchTest -> ^( NEGATION searchTest ) | searchTest -> searchTest ) + int alt26=2; + alt26 = dfa26.predict(input); + switch (alt26) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:554:9: NOT searchTest + { + NOT67=(Token)match(input,NOT,FOLLOW_NOT_in_searchNotCondition2501); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_NOT.add(NOT67); + + pushFollow(FOLLOW_searchTest_in_searchNotCondition2503); + searchTest68=searchTest(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_searchTest.add(searchTest68.getTree()); + // AST REWRITE + // elements: searchTest + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 555:17: -> ^( NEGATION searchTest ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:556:25: ^( NEGATION searchTest ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(NEGATION, "NEGATION"), root_1); + adaptor.addChild(root_1, stream_searchTest.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:557:11: searchTest + { + pushFollow(FOLLOW_searchTest_in_searchNotCondition2563); + searchTest69=searchTest(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_searchTest.add(searchTest69.getTree()); + // AST REWRITE + // elements: searchTest + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 558:17: -> searchTest + { + adaptor.addChild(root_0, stream_searchTest.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "searchNotCondition" + + + public static class searchTest_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "searchTest" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:561:1: searchTest : ( predicate -> predicate | LPAREN searchOrCondition RPAREN -> searchOrCondition ); + public final CMISParser.searchTest_return searchTest() throws RecognitionException { + CMISParser.searchTest_return retval = new CMISParser.searchTest_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token LPAREN71=null; + Token RPAREN73=null; + ParserRuleReturnScope predicate70 =null; + ParserRuleReturnScope searchOrCondition72 =null; + + Object LPAREN71_tree=null; + Object RPAREN73_tree=null; + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleSubtreeStream stream_predicate=new RewriteRuleSubtreeStream(adaptor,"rule predicate"); + RewriteRuleSubtreeStream stream_searchOrCondition=new RewriteRuleSubtreeStream(adaptor,"rule searchOrCondition"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:562:9: ( predicate -> predicate | LPAREN searchOrCondition RPAREN -> searchOrCondition ) + int alt27=2; + int LA27_0 = input.LA(1); + if ( (LA27_0==ID) ) { + alt27=1; + } + else if ( (LA27_0==DOUBLE_QUOTE) && ((strict == false))) { + alt27=1; + } + else if ( (LA27_0==SCORE) ) { + alt27=1; + } + else if ( (LA27_0==AND||LA27_0==AS||LA27_0==FROM||(LA27_0 >= IN && LA27_0 <= INNER)||(LA27_0 >= IS && LA27_0 <= LEFT)||LA27_0==LIKE||LA27_0==NOT||LA27_0==NULL||(LA27_0 >= ON && LA27_0 <= OR)||LA27_0==OUTER||LA27_0==SELECT||LA27_0==WHERE) && ((strict == false))) { + alt27=1; + } + else if ( (LA27_0==ANY||LA27_0==CONTAINS||(LA27_0 >= IN_FOLDER && LA27_0 <= IN_TREE)) ) { + alt27=1; + } + else if ( (LA27_0==ASC||LA27_0==BY||LA27_0==DESC||LA27_0==ORDER) && ((strict == false))) { + alt27=1; + } + else if ( (LA27_0==DECIMAL_INTEGER_LITERAL||(LA27_0 >= FALSE && LA27_0 <= FLOATING_POINT_LITERAL)||LA27_0==QUOTED_STRING||(LA27_0 >= TIMESTAMP && LA27_0 <= TRUE)) ) { + alt27=1; + } + else if ( (LA27_0==COLON) && ((strict == false))) { + alt27=1; + } + else if ( (LA27_0==LPAREN) ) { + alt27=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 27, 0, input); + throw nvae; + } + + switch (alt27) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:563:9: predicate + { + pushFollow(FOLLOW_predicate_in_searchTest2616); + predicate70=predicate(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_predicate.add(predicate70.getTree()); + // AST REWRITE + // elements: predicate + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 564:17: -> predicate + { + adaptor.addChild(root_0, stream_predicate.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:565:11: LPAREN searchOrCondition RPAREN + { + LPAREN71=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_searchTest2648); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(LPAREN71); + + pushFollow(FOLLOW_searchOrCondition_in_searchTest2650); + searchOrCondition72=searchOrCondition(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_searchOrCondition.add(searchOrCondition72.getTree()); + RPAREN73=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_searchTest2652); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(RPAREN73); + + // AST REWRITE + // elements: searchOrCondition + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 566:17: -> searchOrCondition + { + adaptor.addChild(root_0, stream_searchOrCondition.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "searchTest" + + + public static class predicate_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "predicate" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:569:1: predicate : ( comparisonPredicate | inPredicate | likePredicate | nullPredicate | quantifiedComparisonPredicate | quantifiedInPredicate | textSearchPredicate | folderPredicate ); + public final CMISParser.predicate_return predicate() throws RecognitionException { + CMISParser.predicate_return retval = new CMISParser.predicate_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope comparisonPredicate74 =null; + ParserRuleReturnScope inPredicate75 =null; + ParserRuleReturnScope likePredicate76 =null; + ParserRuleReturnScope nullPredicate77 =null; + ParserRuleReturnScope quantifiedComparisonPredicate78 =null; + ParserRuleReturnScope quantifiedInPredicate79 =null; + ParserRuleReturnScope textSearchPredicate80 =null; + ParserRuleReturnScope folderPredicate81 =null; + + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:570:9: ( comparisonPredicate | inPredicate | likePredicate | nullPredicate | quantifiedComparisonPredicate | quantifiedInPredicate | textSearchPredicate | folderPredicate ) + int alt28=8; + alt28 = dfa28.predict(input); + switch (alt28) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:571:9: comparisonPredicate + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_comparisonPredicate_in_predicate2705); + comparisonPredicate74=comparisonPredicate(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, comparisonPredicate74.getTree()); + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:572:11: inPredicate + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_inPredicate_in_predicate2717); + inPredicate75=inPredicate(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, inPredicate75.getTree()); + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:573:11: likePredicate + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_likePredicate_in_predicate2729); + likePredicate76=likePredicate(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, likePredicate76.getTree()); + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:574:11: nullPredicate + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_nullPredicate_in_predicate2741); + nullPredicate77=nullPredicate(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, nullPredicate77.getTree()); + + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:575:11: quantifiedComparisonPredicate + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_quantifiedComparisonPredicate_in_predicate2753); + quantifiedComparisonPredicate78=quantifiedComparisonPredicate(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, quantifiedComparisonPredicate78.getTree()); + + } + break; + case 6 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:576:11: quantifiedInPredicate + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_quantifiedInPredicate_in_predicate2765); + quantifiedInPredicate79=quantifiedInPredicate(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, quantifiedInPredicate79.getTree()); + + } + break; + case 7 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:577:11: textSearchPredicate + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_textSearchPredicate_in_predicate2777); + textSearchPredicate80=textSearchPredicate(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, textSearchPredicate80.getTree()); + + } + break; + case 8 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:578:11: folderPredicate + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_folderPredicate_in_predicate2789); + folderPredicate81=folderPredicate(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, folderPredicate81.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "predicate" + + + public static class comparisonPredicate_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "comparisonPredicate" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:581:1: comparisonPredicate : valueExpression compOp literalOrParameterName -> ^( PRED_COMPARISON SINGLE_VALUED_PROPERTY valueExpression compOp literalOrParameterName ) ; + public final CMISParser.comparisonPredicate_return comparisonPredicate() throws RecognitionException { + CMISParser.comparisonPredicate_return retval = new CMISParser.comparisonPredicate_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope valueExpression82 =null; + ParserRuleReturnScope compOp83 =null; + ParserRuleReturnScope literalOrParameterName84 =null; + + RewriteRuleSubtreeStream stream_valueExpression=new RewriteRuleSubtreeStream(adaptor,"rule valueExpression"); + RewriteRuleSubtreeStream stream_compOp=new RewriteRuleSubtreeStream(adaptor,"rule compOp"); + RewriteRuleSubtreeStream stream_literalOrParameterName=new RewriteRuleSubtreeStream(adaptor,"rule literalOrParameterName"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:582:9: ( valueExpression compOp literalOrParameterName -> ^( PRED_COMPARISON SINGLE_VALUED_PROPERTY valueExpression compOp literalOrParameterName ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:583:9: valueExpression compOp literalOrParameterName + { + pushFollow(FOLLOW_valueExpression_in_comparisonPredicate2822); + valueExpression82=valueExpression(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_valueExpression.add(valueExpression82.getTree()); + pushFollow(FOLLOW_compOp_in_comparisonPredicate2824); + compOp83=compOp(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_compOp.add(compOp83.getTree()); + pushFollow(FOLLOW_literalOrParameterName_in_comparisonPredicate2826); + literalOrParameterName84=literalOrParameterName(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_literalOrParameterName.add(literalOrParameterName84.getTree()); + // AST REWRITE + // elements: literalOrParameterName, valueExpression, compOp + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 584:17: -> ^( PRED_COMPARISON SINGLE_VALUED_PROPERTY valueExpression compOp literalOrParameterName ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:585:25: ^( PRED_COMPARISON SINGLE_VALUED_PROPERTY valueExpression compOp literalOrParameterName ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PRED_COMPARISON, "PRED_COMPARISON"), root_1); + adaptor.addChild(root_1, (Object)adaptor.create(SINGLE_VALUED_PROPERTY, "SINGLE_VALUED_PROPERTY")); + adaptor.addChild(root_1, stream_valueExpression.nextTree()); + adaptor.addChild(root_1, stream_compOp.nextTree()); + adaptor.addChild(root_1, stream_literalOrParameterName.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "comparisonPredicate" + + + public static class compOp_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "compOp" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:588:1: compOp : ( EQUALS | NOTEQUALS | LESSTHAN | GREATERTHAN | LESSTHANOREQUALS | GREATERTHANOREQUALS ); + public final CMISParser.compOp_return compOp() throws RecognitionException { + CMISParser.compOp_return retval = new CMISParser.compOp_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set85=null; + + Object set85_tree=null; + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:589:9: ( EQUALS | NOTEQUALS | LESSTHAN | GREATERTHAN | LESSTHANOREQUALS | GREATERTHANOREQUALS ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g: + { + root_0 = (Object)adaptor.nil(); + + + set85=input.LT(1); + if ( input.LA(1)==EQUALS||(input.LA(1) >= GREATERTHAN && input.LA(1) <= GREATERTHANOREQUALS)||(input.LA(1) >= LESSTHAN && input.LA(1) <= LESSTHANOREQUALS)||input.LA(1)==NOTEQUALS ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set85)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "compOp" + + + public static class literalOrParameterName_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "literalOrParameterName" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:598:1: literalOrParameterName : ( literal |{...}? => parameterName ); + public final CMISParser.literalOrParameterName_return literalOrParameterName() throws RecognitionException { + CMISParser.literalOrParameterName_return retval = new CMISParser.literalOrParameterName_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope literal86 =null; + ParserRuleReturnScope parameterName87 =null; + + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:599:9: ( literal |{...}? => parameterName ) + int alt29=2; + int LA29_0 = input.LA(1); + if ( (LA29_0==DECIMAL_INTEGER_LITERAL||(LA29_0 >= FALSE && LA29_0 <= FLOATING_POINT_LITERAL)||LA29_0==QUOTED_STRING||(LA29_0 >= TIMESTAMP && LA29_0 <= TRUE)) ) { + alt29=1; + } + else if ( (LA29_0==COLON) && ((strict == false))) { + alt29=2; + } + + switch (alt29) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:600:9: literal + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_literal_in_literalOrParameterName3006); + literal86=literal(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, literal86.getTree()); + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:601:11: {...}? => parameterName + { + root_0 = (Object)adaptor.nil(); + + + if ( !((strict == false)) ) { + if (state.backtracking>0) {state.failed=true; return retval;} + throw new FailedPredicateException(input, "literalOrParameterName", "strict == false"); + } + pushFollow(FOLLOW_parameterName_in_literalOrParameterName3021); + parameterName87=parameterName(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, parameterName87.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "literalOrParameterName" + + + public static class literal_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "literal" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:604:1: literal : ( signedNumericLiteral | characterStringLiteral | booleanLiteral | datetimeLiteral ); + public final CMISParser.literal_return literal() throws RecognitionException { + CMISParser.literal_return retval = new CMISParser.literal_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope signedNumericLiteral88 =null; + ParserRuleReturnScope characterStringLiteral89 =null; + ParserRuleReturnScope booleanLiteral90 =null; + ParserRuleReturnScope datetimeLiteral91 =null; + + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:605:9: ( signedNumericLiteral | characterStringLiteral | booleanLiteral | datetimeLiteral ) + int alt30=4; + switch ( input.LA(1) ) { + case DECIMAL_INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + { + alt30=1; + } + break; + case QUOTED_STRING: + { + alt30=2; + } + break; + case FALSE: + case TRUE: + { + alt30=3; + } + break; + case TIMESTAMP: + { + alt30=4; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 30, 0, input); + throw nvae; + } + switch (alt30) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:606:9: signedNumericLiteral + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_signedNumericLiteral_in_literal3054); + signedNumericLiteral88=signedNumericLiteral(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, signedNumericLiteral88.getTree()); + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:607:11: characterStringLiteral + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_characterStringLiteral_in_literal3066); + characterStringLiteral89=characterStringLiteral(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, characterStringLiteral89.getTree()); + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:608:11: booleanLiteral + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_booleanLiteral_in_literal3078); + booleanLiteral90=booleanLiteral(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, booleanLiteral90.getTree()); + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:609:11: datetimeLiteral + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_datetimeLiteral_in_literal3090); + datetimeLiteral91=datetimeLiteral(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, datetimeLiteral91.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "literal" + + + public static class inPredicate_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "inPredicate" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:612:1: inPredicate : columnReference ( NOT )? IN LPAREN inValueList RPAREN -> ^( PRED_IN SINGLE_VALUED_PROPERTY columnReference inValueList ( NOT )? ) ; + public final CMISParser.inPredicate_return inPredicate() throws RecognitionException { + CMISParser.inPredicate_return retval = new CMISParser.inPredicate_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token NOT93=null; + Token IN94=null; + Token LPAREN95=null; + Token RPAREN97=null; + ParserRuleReturnScope columnReference92 =null; + ParserRuleReturnScope inValueList96 =null; + + Object NOT93_tree=null; + Object IN94_tree=null; + Object LPAREN95_tree=null; + Object RPAREN97_tree=null; + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_IN=new RewriteRuleTokenStream(adaptor,"token IN"); + RewriteRuleTokenStream stream_NOT=new RewriteRuleTokenStream(adaptor,"token NOT"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleSubtreeStream stream_columnReference=new RewriteRuleSubtreeStream(adaptor,"rule columnReference"); + RewriteRuleSubtreeStream stream_inValueList=new RewriteRuleSubtreeStream(adaptor,"rule inValueList"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:613:9: ( columnReference ( NOT )? IN LPAREN inValueList RPAREN -> ^( PRED_IN SINGLE_VALUED_PROPERTY columnReference inValueList ( NOT )? ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:614:9: columnReference ( NOT )? IN LPAREN inValueList RPAREN + { + pushFollow(FOLLOW_columnReference_in_inPredicate3123); + columnReference92=columnReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_columnReference.add(columnReference92.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:614:25: ( NOT )? + int alt31=2; + int LA31_0 = input.LA(1); + if ( (LA31_0==NOT) ) { + alt31=1; + } + switch (alt31) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:614:25: NOT + { + NOT93=(Token)match(input,NOT,FOLLOW_NOT_in_inPredicate3125); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_NOT.add(NOT93); + + } + break; + + } + + IN94=(Token)match(input,IN,FOLLOW_IN_in_inPredicate3128); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_IN.add(IN94); + + LPAREN95=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_inPredicate3130); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(LPAREN95); + + pushFollow(FOLLOW_inValueList_in_inPredicate3132); + inValueList96=inValueList(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_inValueList.add(inValueList96.getTree()); + RPAREN97=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_inPredicate3134); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(RPAREN97); + + // AST REWRITE + // elements: columnReference, NOT, inValueList + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 615:17: -> ^( PRED_IN SINGLE_VALUED_PROPERTY columnReference inValueList ( NOT )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:616:25: ^( PRED_IN SINGLE_VALUED_PROPERTY columnReference inValueList ( NOT )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PRED_IN, "PRED_IN"), root_1); + adaptor.addChild(root_1, (Object)adaptor.create(SINGLE_VALUED_PROPERTY, "SINGLE_VALUED_PROPERTY")); + adaptor.addChild(root_1, stream_columnReference.nextTree()); + adaptor.addChild(root_1, stream_inValueList.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:616:86: ( NOT )? + if ( stream_NOT.hasNext() ) { + adaptor.addChild(root_1, stream_NOT.nextNode()); + } + stream_NOT.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "inPredicate" + + + public static class inValueList_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "inValueList" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:619:1: inValueList : literalOrParameterName ( COMMA literalOrParameterName )* -> ^( LIST ( literalOrParameterName )+ ) ; + public final CMISParser.inValueList_return inValueList() throws RecognitionException { + CMISParser.inValueList_return retval = new CMISParser.inValueList_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token COMMA99=null; + ParserRuleReturnScope literalOrParameterName98 =null; + ParserRuleReturnScope literalOrParameterName100 =null; + + Object COMMA99_tree=null; + RewriteRuleTokenStream stream_COMMA=new RewriteRuleTokenStream(adaptor,"token COMMA"); + RewriteRuleSubtreeStream stream_literalOrParameterName=new RewriteRuleSubtreeStream(adaptor,"rule literalOrParameterName"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:620:9: ( literalOrParameterName ( COMMA literalOrParameterName )* -> ^( LIST ( literalOrParameterName )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:621:9: literalOrParameterName ( COMMA literalOrParameterName )* + { + pushFollow(FOLLOW_literalOrParameterName_in_inValueList3222); + literalOrParameterName98=literalOrParameterName(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_literalOrParameterName.add(literalOrParameterName98.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:621:32: ( COMMA literalOrParameterName )* + loop32: + while (true) { + int alt32=2; + int LA32_0 = input.LA(1); + if ( (LA32_0==COMMA) ) { + alt32=1; + } + + switch (alt32) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:621:33: COMMA literalOrParameterName + { + COMMA99=(Token)match(input,COMMA,FOLLOW_COMMA_in_inValueList3225); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_COMMA.add(COMMA99); + + pushFollow(FOLLOW_literalOrParameterName_in_inValueList3227); + literalOrParameterName100=literalOrParameterName(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_literalOrParameterName.add(literalOrParameterName100.getTree()); + } + break; + + default : + break loop32; + } + } + + // AST REWRITE + // elements: literalOrParameterName + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 622:17: -> ^( LIST ( literalOrParameterName )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:623:25: ^( LIST ( literalOrParameterName )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(LIST, "LIST"), root_1); + if ( !(stream_literalOrParameterName.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_literalOrParameterName.hasNext() ) { + adaptor.addChild(root_1, stream_literalOrParameterName.nextTree()); + } + stream_literalOrParameterName.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "inValueList" + + + public static class likePredicate_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "likePredicate" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:626:1: likePredicate : columnReference ( NOT )? LIKE characterStringLiteral -> ^( PRED_LIKE columnReference characterStringLiteral ( NOT )? ) ; + public final CMISParser.likePredicate_return likePredicate() throws RecognitionException { + CMISParser.likePredicate_return retval = new CMISParser.likePredicate_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token NOT102=null; + Token LIKE103=null; + ParserRuleReturnScope columnReference101 =null; + ParserRuleReturnScope characterStringLiteral104 =null; + + Object NOT102_tree=null; + Object LIKE103_tree=null; + RewriteRuleTokenStream stream_NOT=new RewriteRuleTokenStream(adaptor,"token NOT"); + RewriteRuleTokenStream stream_LIKE=new RewriteRuleTokenStream(adaptor,"token LIKE"); + RewriteRuleSubtreeStream stream_columnReference=new RewriteRuleSubtreeStream(adaptor,"rule columnReference"); + RewriteRuleSubtreeStream stream_characterStringLiteral=new RewriteRuleSubtreeStream(adaptor,"rule characterStringLiteral"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:627:9: ( columnReference ( NOT )? LIKE characterStringLiteral -> ^( PRED_LIKE columnReference characterStringLiteral ( NOT )? ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:628:9: columnReference ( NOT )? LIKE characterStringLiteral + { + pushFollow(FOLLOW_columnReference_in_likePredicate3311); + columnReference101=columnReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_columnReference.add(columnReference101.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:628:25: ( NOT )? + int alt33=2; + int LA33_0 = input.LA(1); + if ( (LA33_0==NOT) ) { + alt33=1; + } + switch (alt33) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:628:25: NOT + { + NOT102=(Token)match(input,NOT,FOLLOW_NOT_in_likePredicate3313); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_NOT.add(NOT102); + + } + break; + + } + + LIKE103=(Token)match(input,LIKE,FOLLOW_LIKE_in_likePredicate3316); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LIKE.add(LIKE103); + + pushFollow(FOLLOW_characterStringLiteral_in_likePredicate3318); + characterStringLiteral104=characterStringLiteral(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_characterStringLiteral.add(characterStringLiteral104.getTree()); + // AST REWRITE + // elements: NOT, characterStringLiteral, columnReference + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 629:17: -> ^( PRED_LIKE columnReference characterStringLiteral ( NOT )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:630:25: ^( PRED_LIKE columnReference characterStringLiteral ( NOT )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PRED_LIKE, "PRED_LIKE"), root_1); + adaptor.addChild(root_1, stream_columnReference.nextTree()); + adaptor.addChild(root_1, stream_characterStringLiteral.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:630:76: ( NOT )? + if ( stream_NOT.hasNext() ) { + adaptor.addChild(root_1, stream_NOT.nextNode()); + } + stream_NOT.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "likePredicate" + + + public static class nullPredicate_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "nullPredicate" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:633:1: nullPredicate : ( columnReference IS NULL -> ^( PRED_EXISTS columnReference NOT ) | columnReference IS NOT NULL -> ^( PRED_EXISTS columnReference ) ); + public final CMISParser.nullPredicate_return nullPredicate() throws RecognitionException { + CMISParser.nullPredicate_return retval = new CMISParser.nullPredicate_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token IS106=null; + Token NULL107=null; + Token IS109=null; + Token NOT110=null; + Token NULL111=null; + ParserRuleReturnScope columnReference105 =null; + ParserRuleReturnScope columnReference108 =null; + + Object IS106_tree=null; + Object NULL107_tree=null; + Object IS109_tree=null; + Object NOT110_tree=null; + Object NULL111_tree=null; + RewriteRuleTokenStream stream_NOT=new RewriteRuleTokenStream(adaptor,"token NOT"); + RewriteRuleTokenStream stream_IS=new RewriteRuleTokenStream(adaptor,"token IS"); + RewriteRuleTokenStream stream_NULL=new RewriteRuleTokenStream(adaptor,"token NULL"); + RewriteRuleSubtreeStream stream_columnReference=new RewriteRuleSubtreeStream(adaptor,"rule columnReference"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:634:9: ( columnReference IS NULL -> ^( PRED_EXISTS columnReference NOT ) | columnReference IS NOT NULL -> ^( PRED_EXISTS columnReference ) ) + int alt34=2; + alt34 = dfa34.predict(input); + switch (alt34) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:635:9: columnReference IS NULL + { + pushFollow(FOLLOW_columnReference_in_nullPredicate3404); + columnReference105=columnReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_columnReference.add(columnReference105.getTree()); + IS106=(Token)match(input,IS,FOLLOW_IS_in_nullPredicate3406); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_IS.add(IS106); + + NULL107=(Token)match(input,NULL,FOLLOW_NULL_in_nullPredicate3408); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_NULL.add(NULL107); + + // AST REWRITE + // elements: columnReference + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 636:17: -> ^( PRED_EXISTS columnReference NOT ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:637:25: ^( PRED_EXISTS columnReference NOT ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PRED_EXISTS, "PRED_EXISTS"), root_1); + adaptor.addChild(root_1, stream_columnReference.nextTree()); + adaptor.addChild(root_1, (Object)adaptor.create(NOT, "NOT")); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:638:11: columnReference IS NOT NULL + { + pushFollow(FOLLOW_columnReference_in_nullPredicate3470); + columnReference108=columnReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_columnReference.add(columnReference108.getTree()); + IS109=(Token)match(input,IS,FOLLOW_IS_in_nullPredicate3472); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_IS.add(IS109); + + NOT110=(Token)match(input,NOT,FOLLOW_NOT_in_nullPredicate3474); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_NOT.add(NOT110); + + NULL111=(Token)match(input,NULL,FOLLOW_NULL_in_nullPredicate3476); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_NULL.add(NULL111); + + // AST REWRITE + // elements: columnReference + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 639:17: -> ^( PRED_EXISTS columnReference ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:640:25: ^( PRED_EXISTS columnReference ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PRED_EXISTS, "PRED_EXISTS"), root_1); + adaptor.addChild(root_1, stream_columnReference.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "nullPredicate" + + + public static class quantifiedComparisonPredicate_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "quantifiedComparisonPredicate" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:643:1: quantifiedComparisonPredicate : literalOrParameterName compOp ANY columnReference -> ^( PRED_COMPARISON ANY literalOrParameterName compOp columnReference ) ; + public final CMISParser.quantifiedComparisonPredicate_return quantifiedComparisonPredicate() throws RecognitionException { + CMISParser.quantifiedComparisonPredicate_return retval = new CMISParser.quantifiedComparisonPredicate_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token ANY114=null; + ParserRuleReturnScope literalOrParameterName112 =null; + ParserRuleReturnScope compOp113 =null; + ParserRuleReturnScope columnReference115 =null; + + Object ANY114_tree=null; + RewriteRuleTokenStream stream_ANY=new RewriteRuleTokenStream(adaptor,"token ANY"); + RewriteRuleSubtreeStream stream_columnReference=new RewriteRuleSubtreeStream(adaptor,"rule columnReference"); + RewriteRuleSubtreeStream stream_compOp=new RewriteRuleSubtreeStream(adaptor,"rule compOp"); + RewriteRuleSubtreeStream stream_literalOrParameterName=new RewriteRuleSubtreeStream(adaptor,"rule literalOrParameterName"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:644:9: ( literalOrParameterName compOp ANY columnReference -> ^( PRED_COMPARISON ANY literalOrParameterName compOp columnReference ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:645:9: literalOrParameterName compOp ANY columnReference + { + pushFollow(FOLLOW_literalOrParameterName_in_quantifiedComparisonPredicate3557); + literalOrParameterName112=literalOrParameterName(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_literalOrParameterName.add(literalOrParameterName112.getTree()); + pushFollow(FOLLOW_compOp_in_quantifiedComparisonPredicate3559); + compOp113=compOp(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_compOp.add(compOp113.getTree()); + ANY114=(Token)match(input,ANY,FOLLOW_ANY_in_quantifiedComparisonPredicate3561); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ANY.add(ANY114); + + pushFollow(FOLLOW_columnReference_in_quantifiedComparisonPredicate3563); + columnReference115=columnReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_columnReference.add(columnReference115.getTree()); + // AST REWRITE + // elements: ANY, literalOrParameterName, columnReference, compOp + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 646:17: -> ^( PRED_COMPARISON ANY literalOrParameterName compOp columnReference ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:647:25: ^( PRED_COMPARISON ANY literalOrParameterName compOp columnReference ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PRED_COMPARISON, "PRED_COMPARISON"), root_1); + adaptor.addChild(root_1, stream_ANY.nextNode()); + adaptor.addChild(root_1, stream_literalOrParameterName.nextTree()); + adaptor.addChild(root_1, stream_compOp.nextTree()); + adaptor.addChild(root_1, stream_columnReference.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "quantifiedComparisonPredicate" + + + public static class quantifiedInPredicate_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "quantifiedInPredicate" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:650:1: quantifiedInPredicate : ANY columnReference ( NOT )? IN LPAREN inValueList RPAREN -> ^( PRED_IN ANY columnReference inValueList ( NOT )? ) ; + public final CMISParser.quantifiedInPredicate_return quantifiedInPredicate() throws RecognitionException { + CMISParser.quantifiedInPredicate_return retval = new CMISParser.quantifiedInPredicate_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token ANY116=null; + Token NOT118=null; + Token IN119=null; + Token LPAREN120=null; + Token RPAREN122=null; + ParserRuleReturnScope columnReference117 =null; + ParserRuleReturnScope inValueList121 =null; + + Object ANY116_tree=null; + Object NOT118_tree=null; + Object IN119_tree=null; + Object LPAREN120_tree=null; + Object RPAREN122_tree=null; + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_ANY=new RewriteRuleTokenStream(adaptor,"token ANY"); + RewriteRuleTokenStream stream_IN=new RewriteRuleTokenStream(adaptor,"token IN"); + RewriteRuleTokenStream stream_NOT=new RewriteRuleTokenStream(adaptor,"token NOT"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleSubtreeStream stream_columnReference=new RewriteRuleSubtreeStream(adaptor,"rule columnReference"); + RewriteRuleSubtreeStream stream_inValueList=new RewriteRuleSubtreeStream(adaptor,"rule inValueList"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:651:9: ( ANY columnReference ( NOT )? IN LPAREN inValueList RPAREN -> ^( PRED_IN ANY columnReference inValueList ( NOT )? ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:652:9: ANY columnReference ( NOT )? IN LPAREN inValueList RPAREN + { + ANY116=(Token)match(input,ANY,FOLLOW_ANY_in_quantifiedInPredicate3650); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ANY.add(ANY116); + + pushFollow(FOLLOW_columnReference_in_quantifiedInPredicate3652); + columnReference117=columnReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_columnReference.add(columnReference117.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:652:29: ( NOT )? + int alt35=2; + int LA35_0 = input.LA(1); + if ( (LA35_0==NOT) ) { + alt35=1; + } + switch (alt35) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:652:29: NOT + { + NOT118=(Token)match(input,NOT,FOLLOW_NOT_in_quantifiedInPredicate3654); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_NOT.add(NOT118); + + } + break; + + } + + IN119=(Token)match(input,IN,FOLLOW_IN_in_quantifiedInPredicate3657); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_IN.add(IN119); + + LPAREN120=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_quantifiedInPredicate3659); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(LPAREN120); + + pushFollow(FOLLOW_inValueList_in_quantifiedInPredicate3661); + inValueList121=inValueList(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_inValueList.add(inValueList121.getTree()); + RPAREN122=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_quantifiedInPredicate3663); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(RPAREN122); + + // AST REWRITE + // elements: columnReference, inValueList, ANY, NOT + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 653:17: -> ^( PRED_IN ANY columnReference inValueList ( NOT )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:654:25: ^( PRED_IN ANY columnReference inValueList ( NOT )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PRED_IN, "PRED_IN"), root_1); + adaptor.addChild(root_1, stream_ANY.nextNode()); + adaptor.addChild(root_1, stream_columnReference.nextTree()); + adaptor.addChild(root_1, stream_inValueList.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:654:67: ( NOT )? + if ( stream_NOT.hasNext() ) { + adaptor.addChild(root_1, stream_NOT.nextNode()); + } + stream_NOT.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "quantifiedInPredicate" + + + public static class textSearchPredicate_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "textSearchPredicate" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:657:1: textSearchPredicate : CONTAINS LPAREN ( qualifier COMMA )? textSearchExpression RPAREN -> ^( PRED_FTS textSearchExpression ( qualifier )? ) ; + public final CMISParser.textSearchPredicate_return textSearchPredicate() throws RecognitionException { + CMISParser.textSearchPredicate_return retval = new CMISParser.textSearchPredicate_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token CONTAINS123=null; + Token LPAREN124=null; + Token COMMA126=null; + Token RPAREN128=null; + ParserRuleReturnScope qualifier125 =null; + ParserRuleReturnScope textSearchExpression127 =null; + + Object CONTAINS123_tree=null; + Object LPAREN124_tree=null; + Object COMMA126_tree=null; + Object RPAREN128_tree=null; + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_COMMA=new RewriteRuleTokenStream(adaptor,"token COMMA"); + RewriteRuleTokenStream stream_CONTAINS=new RewriteRuleTokenStream(adaptor,"token CONTAINS"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleSubtreeStream stream_qualifier=new RewriteRuleSubtreeStream(adaptor,"rule qualifier"); + RewriteRuleSubtreeStream stream_textSearchExpression=new RewriteRuleSubtreeStream(adaptor,"rule textSearchExpression"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:658:9: ( CONTAINS LPAREN ( qualifier COMMA )? textSearchExpression RPAREN -> ^( PRED_FTS textSearchExpression ( qualifier )? ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:659:9: CONTAINS LPAREN ( qualifier COMMA )? textSearchExpression RPAREN + { + CONTAINS123=(Token)match(input,CONTAINS,FOLLOW_CONTAINS_in_textSearchPredicate3751); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_CONTAINS.add(CONTAINS123); + + LPAREN124=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_textSearchPredicate3753); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(LPAREN124); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:659:25: ( qualifier COMMA )? + int alt36=2; + int LA36_0 = input.LA(1); + if ( (LA36_0==ID) ) { + alt36=1; + } + else if ( (LA36_0==DOUBLE_QUOTE) && ((strict == false))) { + alt36=1; + } + switch (alt36) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:659:26: qualifier COMMA + { + pushFollow(FOLLOW_qualifier_in_textSearchPredicate3756); + qualifier125=qualifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_qualifier.add(qualifier125.getTree()); + COMMA126=(Token)match(input,COMMA,FOLLOW_COMMA_in_textSearchPredicate3758); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_COMMA.add(COMMA126); + + } + break; + + } + + pushFollow(FOLLOW_textSearchExpression_in_textSearchPredicate3762); + textSearchExpression127=textSearchExpression(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_textSearchExpression.add(textSearchExpression127.getTree()); + RPAREN128=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_textSearchPredicate3764); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(RPAREN128); + + // AST REWRITE + // elements: qualifier, textSearchExpression + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 660:17: -> ^( PRED_FTS textSearchExpression ( qualifier )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:661:25: ^( PRED_FTS textSearchExpression ( qualifier )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PRED_FTS, "PRED_FTS"), root_1); + adaptor.addChild(root_1, stream_textSearchExpression.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:661:57: ( qualifier )? + if ( stream_qualifier.hasNext() ) { + adaptor.addChild(root_1, stream_qualifier.nextTree()); + } + stream_qualifier.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "textSearchPredicate" + + + public static class folderPredicate_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "folderPredicate" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:664:1: folderPredicate : ( IN_FOLDER folderPredicateArgs -> ^( PRED_CHILD folderPredicateArgs ) | IN_TREE folderPredicateArgs -> ^( PRED_DESCENDANT folderPredicateArgs ) ); + public final CMISParser.folderPredicate_return folderPredicate() throws RecognitionException { + CMISParser.folderPredicate_return retval = new CMISParser.folderPredicate_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token IN_FOLDER129=null; + Token IN_TREE131=null; + ParserRuleReturnScope folderPredicateArgs130 =null; + ParserRuleReturnScope folderPredicateArgs132 =null; + + Object IN_FOLDER129_tree=null; + Object IN_TREE131_tree=null; + RewriteRuleTokenStream stream_IN_TREE=new RewriteRuleTokenStream(adaptor,"token IN_TREE"); + RewriteRuleTokenStream stream_IN_FOLDER=new RewriteRuleTokenStream(adaptor,"token IN_FOLDER"); + RewriteRuleSubtreeStream stream_folderPredicateArgs=new RewriteRuleSubtreeStream(adaptor,"rule folderPredicateArgs"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:665:9: ( IN_FOLDER folderPredicateArgs -> ^( PRED_CHILD folderPredicateArgs ) | IN_TREE folderPredicateArgs -> ^( PRED_DESCENDANT folderPredicateArgs ) ) + int alt37=2; + int LA37_0 = input.LA(1); + if ( (LA37_0==IN_FOLDER) ) { + alt37=1; + } + else if ( (LA37_0==IN_TREE) ) { + alt37=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 37, 0, input); + throw nvae; + } + + switch (alt37) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:666:9: IN_FOLDER folderPredicateArgs + { + IN_FOLDER129=(Token)match(input,IN_FOLDER,FOLLOW_IN_FOLDER_in_folderPredicate3848); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_IN_FOLDER.add(IN_FOLDER129); + + pushFollow(FOLLOW_folderPredicateArgs_in_folderPredicate3850); + folderPredicateArgs130=folderPredicateArgs(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_folderPredicateArgs.add(folderPredicateArgs130.getTree()); + // AST REWRITE + // elements: folderPredicateArgs + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 667:17: -> ^( PRED_CHILD folderPredicateArgs ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:668:25: ^( PRED_CHILD folderPredicateArgs ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PRED_CHILD, "PRED_CHILD"), root_1); + adaptor.addChild(root_1, stream_folderPredicateArgs.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:669:11: IN_TREE folderPredicateArgs + { + IN_TREE131=(Token)match(input,IN_TREE,FOLLOW_IN_TREE_in_folderPredicate3910); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_IN_TREE.add(IN_TREE131); + + pushFollow(FOLLOW_folderPredicateArgs_in_folderPredicate3912); + folderPredicateArgs132=folderPredicateArgs(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_folderPredicateArgs.add(folderPredicateArgs132.getTree()); + // AST REWRITE + // elements: folderPredicateArgs + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 670:17: -> ^( PRED_DESCENDANT folderPredicateArgs ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:671:25: ^( PRED_DESCENDANT folderPredicateArgs ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PRED_DESCENDANT, "PRED_DESCENDANT"), root_1); + adaptor.addChild(root_1, stream_folderPredicateArgs.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "folderPredicate" + + + public static class folderPredicateArgs_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "folderPredicateArgs" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:674:1: folderPredicateArgs : LPAREN ( qualifier COMMA )? folderId RPAREN -> folderId ( qualifier )? ; + public final CMISParser.folderPredicateArgs_return folderPredicateArgs() throws RecognitionException { + CMISParser.folderPredicateArgs_return retval = new CMISParser.folderPredicateArgs_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token LPAREN133=null; + Token COMMA135=null; + Token RPAREN137=null; + ParserRuleReturnScope qualifier134 =null; + ParserRuleReturnScope folderId136 =null; + + Object LPAREN133_tree=null; + Object COMMA135_tree=null; + Object RPAREN137_tree=null; + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleTokenStream stream_COMMA=new RewriteRuleTokenStream(adaptor,"token COMMA"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleSubtreeStream stream_qualifier=new RewriteRuleSubtreeStream(adaptor,"rule qualifier"); + RewriteRuleSubtreeStream stream_folderId=new RewriteRuleSubtreeStream(adaptor,"rule folderId"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:675:9: ( LPAREN ( qualifier COMMA )? folderId RPAREN -> folderId ( qualifier )? ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:676:9: LPAREN ( qualifier COMMA )? folderId RPAREN + { + LPAREN133=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_folderPredicateArgs3993); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(LPAREN133); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:676:16: ( qualifier COMMA )? + int alt38=2; + int LA38_0 = input.LA(1); + if ( (LA38_0==ID) ) { + alt38=1; + } + else if ( (LA38_0==DOUBLE_QUOTE) && ((strict == false))) { + alt38=1; + } + switch (alt38) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:676:17: qualifier COMMA + { + pushFollow(FOLLOW_qualifier_in_folderPredicateArgs3996); + qualifier134=qualifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_qualifier.add(qualifier134.getTree()); + COMMA135=(Token)match(input,COMMA,FOLLOW_COMMA_in_folderPredicateArgs3998); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_COMMA.add(COMMA135); + + } + break; + + } + + pushFollow(FOLLOW_folderId_in_folderPredicateArgs4002); + folderId136=folderId(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_folderId.add(folderId136.getTree()); + RPAREN137=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_folderPredicateArgs4004); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(RPAREN137); + + // AST REWRITE + // elements: folderId, qualifier + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 677:17: -> folderId ( qualifier )? + { + adaptor.addChild(root_0, stream_folderId.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:677:29: ( qualifier )? + if ( stream_qualifier.hasNext() ) { + adaptor.addChild(root_0, stream_qualifier.nextTree()); + } + stream_qualifier.reset(); + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "folderPredicateArgs" + + + public static class orderByClause_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "orderByClause" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:680:1: orderByClause : ORDER BY sortSpecification ( COMMA sortSpecification )* -> ^( ORDER ( sortSpecification )+ ) ; + public final CMISParser.orderByClause_return orderByClause() throws RecognitionException { + CMISParser.orderByClause_return retval = new CMISParser.orderByClause_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token ORDER138=null; + Token BY139=null; + Token COMMA141=null; + ParserRuleReturnScope sortSpecification140 =null; + ParserRuleReturnScope sortSpecification142 =null; + + Object ORDER138_tree=null; + Object BY139_tree=null; + Object COMMA141_tree=null; + RewriteRuleTokenStream stream_BY=new RewriteRuleTokenStream(adaptor,"token BY"); + RewriteRuleTokenStream stream_ORDER=new RewriteRuleTokenStream(adaptor,"token ORDER"); + RewriteRuleTokenStream stream_COMMA=new RewriteRuleTokenStream(adaptor,"token COMMA"); + RewriteRuleSubtreeStream stream_sortSpecification=new RewriteRuleSubtreeStream(adaptor,"rule sortSpecification"); + + + paraphrases.push("in order by"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:689:9: ( ORDER BY sortSpecification ( COMMA sortSpecification )* -> ^( ORDER ( sortSpecification )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:690:9: ORDER BY sortSpecification ( COMMA sortSpecification )* + { + ORDER138=(Token)match(input,ORDER,FOLLOW_ORDER_in_orderByClause4070); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ORDER.add(ORDER138); + + BY139=(Token)match(input,BY,FOLLOW_BY_in_orderByClause4072); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_BY.add(BY139); + + pushFollow(FOLLOW_sortSpecification_in_orderByClause4074); + sortSpecification140=sortSpecification(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_sortSpecification.add(sortSpecification140.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:690:36: ( COMMA sortSpecification )* + loop39: + while (true) { + int alt39=2; + int LA39_0 = input.LA(1); + if ( (LA39_0==COMMA) ) { + alt39=1; + } + + switch (alt39) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:690:37: COMMA sortSpecification + { + COMMA141=(Token)match(input,COMMA,FOLLOW_COMMA_in_orderByClause4077); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_COMMA.add(COMMA141); + + pushFollow(FOLLOW_sortSpecification_in_orderByClause4079); + sortSpecification142=sortSpecification(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_sortSpecification.add(sortSpecification142.getTree()); + } + break; + + default : + break loop39; + } + } + + // AST REWRITE + // elements: sortSpecification, ORDER + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 691:17: -> ^( ORDER ( sortSpecification )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:692:25: ^( ORDER ( sortSpecification )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(stream_ORDER.nextNode(), root_1); + if ( !(stream_sortSpecification.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_sortSpecification.hasNext() ) { + adaptor.addChild(root_1, stream_sortSpecification.nextTree()); + } + stream_sortSpecification.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + if ( state.backtracking==0 ) { + paraphrases.pop(); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "orderByClause" + + + public static class sortSpecification_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "sortSpecification" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:695:1: sortSpecification : ( columnReference -> ^( SORT_SPECIFICATION columnReference ASC ) | columnReference (by= ASC |by= DESC ) -> ^( SORT_SPECIFICATION columnReference $by) ); + public final CMISParser.sortSpecification_return sortSpecification() throws RecognitionException { + CMISParser.sortSpecification_return retval = new CMISParser.sortSpecification_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token by=null; + ParserRuleReturnScope columnReference143 =null; + ParserRuleReturnScope columnReference144 =null; + + Object by_tree=null; + RewriteRuleTokenStream stream_ASC=new RewriteRuleTokenStream(adaptor,"token ASC"); + RewriteRuleTokenStream stream_DESC=new RewriteRuleTokenStream(adaptor,"token DESC"); + RewriteRuleSubtreeStream stream_columnReference=new RewriteRuleSubtreeStream(adaptor,"rule columnReference"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:696:9: ( columnReference -> ^( SORT_SPECIFICATION columnReference ASC ) | columnReference (by= ASC |by= DESC ) -> ^( SORT_SPECIFICATION columnReference $by) ) + int alt41=2; + alt41 = dfa41.predict(input); + switch (alt41) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:697:9: columnReference + { + pushFollow(FOLLOW_columnReference_in_sortSpecification4163); + columnReference143=columnReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_columnReference.add(columnReference143.getTree()); + // AST REWRITE + // elements: columnReference + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 698:17: -> ^( SORT_SPECIFICATION columnReference ASC ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:699:25: ^( SORT_SPECIFICATION columnReference ASC ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(SORT_SPECIFICATION, "SORT_SPECIFICATION"), root_1); + adaptor.addChild(root_1, stream_columnReference.nextTree()); + adaptor.addChild(root_1, (Object)adaptor.create(ASC, "ASC")); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:700:11: columnReference (by= ASC |by= DESC ) + { + pushFollow(FOLLOW_columnReference_in_sortSpecification4225); + columnReference144=columnReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_columnReference.add(columnReference144.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:701:9: (by= ASC |by= DESC ) + int alt40=2; + int LA40_0 = input.LA(1); + if ( (LA40_0==ASC) ) { + alt40=1; + } + else if ( (LA40_0==DESC) ) { + alt40=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 40, 0, input); + throw nvae; + } + + switch (alt40) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:702:17: by= ASC + { + by=(Token)match(input,ASC,FOLLOW_ASC_in_sortSpecification4255); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ASC.add(by); + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:703:19: by= DESC + { + by=(Token)match(input,DESC,FOLLOW_DESC_in_sortSpecification4277); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DESC.add(by); + + } + break; + + } + + // AST REWRITE + // elements: by, columnReference + // token labels: by + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleTokenStream stream_by=new RewriteRuleTokenStream(adaptor,"token by",by); + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 705:17: -> ^( SORT_SPECIFICATION columnReference $by) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:706:25: ^( SORT_SPECIFICATION columnReference $by) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(SORT_SPECIFICATION, "SORT_SPECIFICATION"), root_1); + adaptor.addChild(root_1, stream_columnReference.nextTree()); + adaptor.addChild(root_1, stream_by.nextNode()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "sortSpecification" + + + public static class correlationName_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "correlationName" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:709:1: correlationName : identifier ; + public final CMISParser.correlationName_return correlationName() throws RecognitionException { + CMISParser.correlationName_return retval = new CMISParser.correlationName_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope identifier145 =null; + + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:710:9: ( identifier ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:711:9: identifier + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_identifier_in_correlationName4371); + identifier145=identifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, identifier145.getTree()); + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "correlationName" + + + public static class tableName_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "tableName" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:719:1: tableName : identifier -> identifier ; + public final CMISParser.tableName_return tableName() throws RecognitionException { + CMISParser.tableName_return retval = new CMISParser.tableName_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope identifier146 =null; + + RewriteRuleSubtreeStream stream_identifier=new RewriteRuleSubtreeStream(adaptor,"rule identifier"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:720:9: ( identifier -> identifier ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:721:9: identifier + { + pushFollow(FOLLOW_identifier_in_tableName4407); + identifier146=identifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identifier.add(identifier146.getTree()); + // AST REWRITE + // elements: identifier + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 722:17: -> identifier + { + adaptor.addChild(root_0, stream_identifier.nextTree()); + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "tableName" + + + public static class columnName_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "columnName" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:725:1: columnName : identifier -> identifier ; + public final CMISParser.columnName_return columnName() throws RecognitionException { + CMISParser.columnName_return retval = new CMISParser.columnName_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope identifier147 =null; + + RewriteRuleSubtreeStream stream_identifier=new RewriteRuleSubtreeStream(adaptor,"rule identifier"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:726:9: ( identifier -> identifier ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:727:9: identifier + { + pushFollow(FOLLOW_identifier_in_columnName4460); + identifier147=identifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identifier.add(identifier147.getTree()); + // AST REWRITE + // elements: identifier + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 728:17: -> identifier + { + adaptor.addChild(root_0, stream_identifier.nextTree()); + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "columnName" + + + public static class parameterName_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "parameterName" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:731:1: parameterName : COLON identifier -> ^( PARAMETER identifier ) ; + public final CMISParser.parameterName_return parameterName() throws RecognitionException { + CMISParser.parameterName_return retval = new CMISParser.parameterName_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token COLON148=null; + ParserRuleReturnScope identifier149 =null; + + Object COLON148_tree=null; + RewriteRuleTokenStream stream_COLON=new RewriteRuleTokenStream(adaptor,"token COLON"); + RewriteRuleSubtreeStream stream_identifier=new RewriteRuleSubtreeStream(adaptor,"rule identifier"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:732:9: ( COLON identifier -> ^( PARAMETER identifier ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:733:9: COLON identifier + { + COLON148=(Token)match(input,COLON,FOLLOW_COLON_in_parameterName4513); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_COLON.add(COLON148); + + pushFollow(FOLLOW_identifier_in_parameterName4515); + identifier149=identifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identifier.add(identifier149.getTree()); + // AST REWRITE + // elements: identifier + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 734:17: -> ^( PARAMETER identifier ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:735:25: ^( PARAMETER identifier ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PARAMETER, "PARAMETER"), root_1); + adaptor.addChild(root_1, stream_identifier.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "parameterName" + + + public static class folderId_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "folderId" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:738:1: folderId : characterStringLiteral -> characterStringLiteral ; + public final CMISParser.folderId_return folderId() throws RecognitionException { + CMISParser.folderId_return retval = new CMISParser.folderId_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope characterStringLiteral150 =null; + + RewriteRuleSubtreeStream stream_characterStringLiteral=new RewriteRuleSubtreeStream(adaptor,"rule characterStringLiteral"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:739:9: ( characterStringLiteral -> characterStringLiteral ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:740:9: characterStringLiteral + { + pushFollow(FOLLOW_characterStringLiteral_in_folderId4596); + characterStringLiteral150=characterStringLiteral(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_characterStringLiteral.add(characterStringLiteral150.getTree()); + // AST REWRITE + // elements: characterStringLiteral + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 741:17: -> characterStringLiteral + { + adaptor.addChild(root_0, stream_characterStringLiteral.nextTree()); + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "folderId" + + + public static class textSearchExpression_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "textSearchExpression" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:744:1: textSearchExpression : QUOTED_STRING ; + public final CMISParser.textSearchExpression_return textSearchExpression() throws RecognitionException { + CMISParser.textSearchExpression_return retval = new CMISParser.textSearchExpression_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token QUOTED_STRING151=null; + + Object QUOTED_STRING151_tree=null; + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:745:9: ( QUOTED_STRING ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:746:9: QUOTED_STRING + { + root_0 = (Object)adaptor.nil(); + + + QUOTED_STRING151=(Token)match(input,QUOTED_STRING,FOLLOW_QUOTED_STRING_in_textSearchExpression4649); if (state.failed) return retval; + if ( state.backtracking==0 ) { + QUOTED_STRING151_tree = (Object)adaptor.create(QUOTED_STRING151); + adaptor.addChild(root_0, QUOTED_STRING151_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "textSearchExpression" + + + public static class identifier_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "identifier" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:749:1: identifier : ( ID -> ID |{...}? => DOUBLE_QUOTE keyWordOrId DOUBLE_QUOTE -> ^( keyWordOrId ) ); + public final CMISParser.identifier_return identifier() throws RecognitionException { + CMISParser.identifier_return retval = new CMISParser.identifier_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token ID152=null; + Token DOUBLE_QUOTE153=null; + Token DOUBLE_QUOTE155=null; + ParserRuleReturnScope keyWordOrId154 =null; + + Object ID152_tree=null; + Object DOUBLE_QUOTE153_tree=null; + Object DOUBLE_QUOTE155_tree=null; + RewriteRuleTokenStream stream_ID=new RewriteRuleTokenStream(adaptor,"token ID"); + RewriteRuleTokenStream stream_DOUBLE_QUOTE=new RewriteRuleTokenStream(adaptor,"token DOUBLE_QUOTE"); + RewriteRuleSubtreeStream stream_keyWordOrId=new RewriteRuleSubtreeStream(adaptor,"rule keyWordOrId"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:750:9: ( ID -> ID |{...}? => DOUBLE_QUOTE keyWordOrId DOUBLE_QUOTE -> ^( keyWordOrId ) ) + int alt42=2; + int LA42_0 = input.LA(1); + if ( (LA42_0==ID) ) { + alt42=1; + } + else if ( (LA42_0==DOUBLE_QUOTE) && ((strict == false))) { + alt42=2; + } + + switch (alt42) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:751:9: ID + { + ID152=(Token)match(input,ID,FOLLOW_ID_in_identifier4682); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ID.add(ID152); + + // AST REWRITE + // elements: ID + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 752:17: -> ID + { + adaptor.addChild(root_0, stream_ID.nextNode()); + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:753:11: {...}? => DOUBLE_QUOTE keyWordOrId DOUBLE_QUOTE + { + if ( !((strict == false)) ) { + if (state.backtracking>0) {state.failed=true; return retval;} + throw new FailedPredicateException(input, "identifier", "strict == false"); + } + DOUBLE_QUOTE153=(Token)match(input,DOUBLE_QUOTE,FOLLOW_DOUBLE_QUOTE_in_identifier4717); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DOUBLE_QUOTE.add(DOUBLE_QUOTE153); + + pushFollow(FOLLOW_keyWordOrId_in_identifier4719); + keyWordOrId154=keyWordOrId(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_keyWordOrId.add(keyWordOrId154.getTree()); + DOUBLE_QUOTE155=(Token)match(input,DOUBLE_QUOTE,FOLLOW_DOUBLE_QUOTE_in_identifier4721); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DOUBLE_QUOTE.add(DOUBLE_QUOTE155); + + // AST REWRITE + // elements: keyWordOrId + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 754:17: -> ^( keyWordOrId ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:755:25: ^( keyWordOrId ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot(stream_keyWordOrId.nextNode(), root_1); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "identifier" + + + public static class signedNumericLiteral_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "signedNumericLiteral" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:758:1: signedNumericLiteral : ( FLOATING_POINT_LITERAL -> ^( NUMERIC_LITERAL FLOATING_POINT_LITERAL ) | integerLiteral -> integerLiteral ); + public final CMISParser.signedNumericLiteral_return signedNumericLiteral() throws RecognitionException { + CMISParser.signedNumericLiteral_return retval = new CMISParser.signedNumericLiteral_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token FLOATING_POINT_LITERAL156=null; + ParserRuleReturnScope integerLiteral157 =null; + + Object FLOATING_POINT_LITERAL156_tree=null; + RewriteRuleTokenStream stream_FLOATING_POINT_LITERAL=new RewriteRuleTokenStream(adaptor,"token FLOATING_POINT_LITERAL"); + RewriteRuleSubtreeStream stream_integerLiteral=new RewriteRuleSubtreeStream(adaptor,"rule integerLiteral"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:759:9: ( FLOATING_POINT_LITERAL -> ^( NUMERIC_LITERAL FLOATING_POINT_LITERAL ) | integerLiteral -> integerLiteral ) + int alt43=2; + int LA43_0 = input.LA(1); + if ( (LA43_0==FLOATING_POINT_LITERAL) ) { + alt43=1; + } + else if ( (LA43_0==DECIMAL_INTEGER_LITERAL) ) { + alt43=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 43, 0, input); + throw nvae; + } + + switch (alt43) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:760:9: FLOATING_POINT_LITERAL + { + FLOATING_POINT_LITERAL156=(Token)match(input,FLOATING_POINT_LITERAL,FOLLOW_FLOATING_POINT_LITERAL_in_signedNumericLiteral4800); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_FLOATING_POINT_LITERAL.add(FLOATING_POINT_LITERAL156); + + // AST REWRITE + // elements: FLOATING_POINT_LITERAL + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 761:17: -> ^( NUMERIC_LITERAL FLOATING_POINT_LITERAL ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:762:25: ^( NUMERIC_LITERAL FLOATING_POINT_LITERAL ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(NUMERIC_LITERAL, "NUMERIC_LITERAL"), root_1); + adaptor.addChild(root_1, stream_FLOATING_POINT_LITERAL.nextNode()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:763:11: integerLiteral + { + pushFollow(FOLLOW_integerLiteral_in_signedNumericLiteral4860); + integerLiteral157=integerLiteral(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_integerLiteral.add(integerLiteral157.getTree()); + // AST REWRITE + // elements: integerLiteral + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 764:17: -> integerLiteral + { + adaptor.addChild(root_0, stream_integerLiteral.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "signedNumericLiteral" + + + public static class integerLiteral_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "integerLiteral" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:767:1: integerLiteral : DECIMAL_INTEGER_LITERAL -> ^( NUMERIC_LITERAL DECIMAL_INTEGER_LITERAL ) ; + public final CMISParser.integerLiteral_return integerLiteral() throws RecognitionException { + CMISParser.integerLiteral_return retval = new CMISParser.integerLiteral_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token DECIMAL_INTEGER_LITERAL158=null; + + Object DECIMAL_INTEGER_LITERAL158_tree=null; + RewriteRuleTokenStream stream_DECIMAL_INTEGER_LITERAL=new RewriteRuleTokenStream(adaptor,"token DECIMAL_INTEGER_LITERAL"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:768:9: ( DECIMAL_INTEGER_LITERAL -> ^( NUMERIC_LITERAL DECIMAL_INTEGER_LITERAL ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:769:9: DECIMAL_INTEGER_LITERAL + { + DECIMAL_INTEGER_LITERAL158=(Token)match(input,DECIMAL_INTEGER_LITERAL,FOLLOW_DECIMAL_INTEGER_LITERAL_in_integerLiteral4913); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DECIMAL_INTEGER_LITERAL.add(DECIMAL_INTEGER_LITERAL158); + + // AST REWRITE + // elements: DECIMAL_INTEGER_LITERAL + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 770:17: -> ^( NUMERIC_LITERAL DECIMAL_INTEGER_LITERAL ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:771:25: ^( NUMERIC_LITERAL DECIMAL_INTEGER_LITERAL ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(NUMERIC_LITERAL, "NUMERIC_LITERAL"), root_1); + adaptor.addChild(root_1, stream_DECIMAL_INTEGER_LITERAL.nextNode()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "integerLiteral" + + + public static class booleanLiteral_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "booleanLiteral" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:774:1: booleanLiteral : ( TRUE -> ^( BOOLEAN_LITERAL TRUE ) | FALSE -> ^( BOOLEAN_LITERAL FALSE ) ); + public final CMISParser.booleanLiteral_return booleanLiteral() throws RecognitionException { + CMISParser.booleanLiteral_return retval = new CMISParser.booleanLiteral_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token TRUE159=null; + Token FALSE160=null; + + Object TRUE159_tree=null; + Object FALSE160_tree=null; + RewriteRuleTokenStream stream_FALSE=new RewriteRuleTokenStream(adaptor,"token FALSE"); + RewriteRuleTokenStream stream_TRUE=new RewriteRuleTokenStream(adaptor,"token TRUE"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:775:9: ( TRUE -> ^( BOOLEAN_LITERAL TRUE ) | FALSE -> ^( BOOLEAN_LITERAL FALSE ) ) + int alt44=2; + int LA44_0 = input.LA(1); + if ( (LA44_0==TRUE) ) { + alt44=1; + } + else if ( (LA44_0==FALSE) ) { + alt44=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 44, 0, input); + throw nvae; + } + + switch (alt44) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:776:9: TRUE + { + TRUE159=(Token)match(input,TRUE,FOLLOW_TRUE_in_booleanLiteral4994); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_TRUE.add(TRUE159); + + // AST REWRITE + // elements: TRUE + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 777:17: -> ^( BOOLEAN_LITERAL TRUE ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:778:25: ^( BOOLEAN_LITERAL TRUE ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(BOOLEAN_LITERAL, "BOOLEAN_LITERAL"), root_1); + adaptor.addChild(root_1, stream_TRUE.nextNode()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:779:11: FALSE + { + FALSE160=(Token)match(input,FALSE,FOLLOW_FALSE_in_booleanLiteral5054); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_FALSE.add(FALSE160); + + // AST REWRITE + // elements: FALSE + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 780:17: -> ^( BOOLEAN_LITERAL FALSE ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:781:25: ^( BOOLEAN_LITERAL FALSE ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(BOOLEAN_LITERAL, "BOOLEAN_LITERAL"), root_1); + adaptor.addChild(root_1, stream_FALSE.nextNode()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "booleanLiteral" + + + public static class datetimeLiteral_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "datetimeLiteral" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:784:1: datetimeLiteral : TIMESTAMP QUOTED_STRING -> ^( DATETIME_LITERAL QUOTED_STRING ) ; + public final CMISParser.datetimeLiteral_return datetimeLiteral() throws RecognitionException { + CMISParser.datetimeLiteral_return retval = new CMISParser.datetimeLiteral_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token TIMESTAMP161=null; + Token QUOTED_STRING162=null; + + Object TIMESTAMP161_tree=null; + Object QUOTED_STRING162_tree=null; + RewriteRuleTokenStream stream_QUOTED_STRING=new RewriteRuleTokenStream(adaptor,"token QUOTED_STRING"); + RewriteRuleTokenStream stream_TIMESTAMP=new RewriteRuleTokenStream(adaptor,"token TIMESTAMP"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:785:9: ( TIMESTAMP QUOTED_STRING -> ^( DATETIME_LITERAL QUOTED_STRING ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:786:9: TIMESTAMP QUOTED_STRING + { + TIMESTAMP161=(Token)match(input,TIMESTAMP,FOLLOW_TIMESTAMP_in_datetimeLiteral5135); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_TIMESTAMP.add(TIMESTAMP161); + + QUOTED_STRING162=(Token)match(input,QUOTED_STRING,FOLLOW_QUOTED_STRING_in_datetimeLiteral5137); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_QUOTED_STRING.add(QUOTED_STRING162); + + // AST REWRITE + // elements: QUOTED_STRING + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 787:17: -> ^( DATETIME_LITERAL QUOTED_STRING ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:788:25: ^( DATETIME_LITERAL QUOTED_STRING ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(DATETIME_LITERAL, "DATETIME_LITERAL"), root_1); + adaptor.addChild(root_1, stream_QUOTED_STRING.nextNode()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "datetimeLiteral" + + + public static class characterStringLiteral_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "characterStringLiteral" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:791:1: characterStringLiteral : QUOTED_STRING -> ^( STRING_LITERAL QUOTED_STRING ) ; + public final CMISParser.characterStringLiteral_return characterStringLiteral() throws RecognitionException { + CMISParser.characterStringLiteral_return retval = new CMISParser.characterStringLiteral_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token QUOTED_STRING163=null; + + Object QUOTED_STRING163_tree=null; + RewriteRuleTokenStream stream_QUOTED_STRING=new RewriteRuleTokenStream(adaptor,"token QUOTED_STRING"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:792:9: ( QUOTED_STRING -> ^( STRING_LITERAL QUOTED_STRING ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:793:9: QUOTED_STRING + { + QUOTED_STRING163=(Token)match(input,QUOTED_STRING,FOLLOW_QUOTED_STRING_in_characterStringLiteral5218); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_QUOTED_STRING.add(QUOTED_STRING163); + + // AST REWRITE + // elements: QUOTED_STRING + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 794:17: -> ^( STRING_LITERAL QUOTED_STRING ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:795:25: ^( STRING_LITERAL QUOTED_STRING ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(STRING_LITERAL, "STRING_LITERAL"), root_1); + adaptor.addChild(root_1, stream_QUOTED_STRING.nextNode()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "characterStringLiteral" + + + public static class keyWord_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "keyWord" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:798:1: keyWord : ( SELECT | AS | FROM | JOIN | INNER | LEFT | OUTER | ON | WHERE | OR | AND | NOT | IN | LIKE | IS | NULL | ANY | CONTAINS | IN_FOLDER | IN_TREE | ORDER | BY | ASC | DESC | TIMESTAMP | TRUE | FALSE | cmisFunction ); + public final CMISParser.keyWord_return keyWord() throws RecognitionException { + CMISParser.keyWord_return retval = new CMISParser.keyWord_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token SELECT164=null; + Token AS165=null; + Token FROM166=null; + Token JOIN167=null; + Token INNER168=null; + Token LEFT169=null; + Token OUTER170=null; + Token ON171=null; + Token WHERE172=null; + Token OR173=null; + Token AND174=null; + Token NOT175=null; + Token IN176=null; + Token LIKE177=null; + Token IS178=null; + Token NULL179=null; + Token ANY180=null; + Token CONTAINS181=null; + Token IN_FOLDER182=null; + Token IN_TREE183=null; + Token ORDER184=null; + Token BY185=null; + Token ASC186=null; + Token DESC187=null; + Token TIMESTAMP188=null; + Token TRUE189=null; + Token FALSE190=null; + ParserRuleReturnScope cmisFunction191 =null; + + Object SELECT164_tree=null; + Object AS165_tree=null; + Object FROM166_tree=null; + Object JOIN167_tree=null; + Object INNER168_tree=null; + Object LEFT169_tree=null; + Object OUTER170_tree=null; + Object ON171_tree=null; + Object WHERE172_tree=null; + Object OR173_tree=null; + Object AND174_tree=null; + Object NOT175_tree=null; + Object IN176_tree=null; + Object LIKE177_tree=null; + Object IS178_tree=null; + Object NULL179_tree=null; + Object ANY180_tree=null; + Object CONTAINS181_tree=null; + Object IN_FOLDER182_tree=null; + Object IN_TREE183_tree=null; + Object ORDER184_tree=null; + Object BY185_tree=null; + Object ASC186_tree=null; + Object DESC187_tree=null; + Object TIMESTAMP188_tree=null; + Object TRUE189_tree=null; + Object FALSE190_tree=null; + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:799:9: ( SELECT | AS | FROM | JOIN | INNER | LEFT | OUTER | ON | WHERE | OR | AND | NOT | IN | LIKE | IS | NULL | ANY | CONTAINS | IN_FOLDER | IN_TREE | ORDER | BY | ASC | DESC | TIMESTAMP | TRUE | FALSE | cmisFunction ) + int alt45=28; + switch ( input.LA(1) ) { + case SELECT: + { + alt45=1; + } + break; + case AS: + { + alt45=2; + } + break; + case FROM: + { + alt45=3; + } + break; + case JOIN: + { + alt45=4; + } + break; + case INNER: + { + alt45=5; + } + break; + case LEFT: + { + alt45=6; + } + break; + case OUTER: + { + alt45=7; + } + break; + case ON: + { + alt45=8; + } + break; + case WHERE: + { + alt45=9; + } + break; + case OR: + { + alt45=10; + } + break; + case AND: + { + alt45=11; + } + break; + case NOT: + { + alt45=12; + } + break; + case IN: + { + alt45=13; + } + break; + case LIKE: + { + alt45=14; + } + break; + case IS: + { + alt45=15; + } + break; + case NULL: + { + alt45=16; + } + break; + case ANY: + { + alt45=17; + } + break; + case CONTAINS: + { + alt45=18; + } + break; + case IN_FOLDER: + { + alt45=19; + } + break; + case IN_TREE: + { + alt45=20; + } + break; + case ORDER: + { + alt45=21; + } + break; + case BY: + { + alt45=22; + } + break; + case ASC: + { + alt45=23; + } + break; + case DESC: + { + alt45=24; + } + break; + case TIMESTAMP: + { + alt45=25; + } + break; + case TRUE: + { + alt45=26; + } + break; + case FALSE: + { + alt45=27; + } + break; + case SCORE: + { + alt45=28; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 45, 0, input); + throw nvae; + } + switch (alt45) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:800:9: SELECT + { + root_0 = (Object)adaptor.nil(); + + + SELECT164=(Token)match(input,SELECT,FOLLOW_SELECT_in_keyWord5299); if (state.failed) return retval; + if ( state.backtracking==0 ) { + SELECT164_tree = (Object)adaptor.create(SELECT164); + adaptor.addChild(root_0, SELECT164_tree); + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:801:11: AS + { + root_0 = (Object)adaptor.nil(); + + + AS165=(Token)match(input,AS,FOLLOW_AS_in_keyWord5311); if (state.failed) return retval; + if ( state.backtracking==0 ) { + AS165_tree = (Object)adaptor.create(AS165); + adaptor.addChild(root_0, AS165_tree); + } + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:802:11: FROM + { + root_0 = (Object)adaptor.nil(); + + + FROM166=(Token)match(input,FROM,FOLLOW_FROM_in_keyWord5323); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FROM166_tree = (Object)adaptor.create(FROM166); + adaptor.addChild(root_0, FROM166_tree); + } + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:803:11: JOIN + { + root_0 = (Object)adaptor.nil(); + + + JOIN167=(Token)match(input,JOIN,FOLLOW_JOIN_in_keyWord5335); if (state.failed) return retval; + if ( state.backtracking==0 ) { + JOIN167_tree = (Object)adaptor.create(JOIN167); + adaptor.addChild(root_0, JOIN167_tree); + } + + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:804:11: INNER + { + root_0 = (Object)adaptor.nil(); + + + INNER168=(Token)match(input,INNER,FOLLOW_INNER_in_keyWord5347); if (state.failed) return retval; + if ( state.backtracking==0 ) { + INNER168_tree = (Object)adaptor.create(INNER168); + adaptor.addChild(root_0, INNER168_tree); + } + + } + break; + case 6 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:805:11: LEFT + { + root_0 = (Object)adaptor.nil(); + + + LEFT169=(Token)match(input,LEFT,FOLLOW_LEFT_in_keyWord5359); if (state.failed) return retval; + if ( state.backtracking==0 ) { + LEFT169_tree = (Object)adaptor.create(LEFT169); + adaptor.addChild(root_0, LEFT169_tree); + } + + } + break; + case 7 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:806:11: OUTER + { + root_0 = (Object)adaptor.nil(); + + + OUTER170=(Token)match(input,OUTER,FOLLOW_OUTER_in_keyWord5371); if (state.failed) return retval; + if ( state.backtracking==0 ) { + OUTER170_tree = (Object)adaptor.create(OUTER170); + adaptor.addChild(root_0, OUTER170_tree); + } + + } + break; + case 8 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:807:11: ON + { + root_0 = (Object)adaptor.nil(); + + + ON171=(Token)match(input,ON,FOLLOW_ON_in_keyWord5383); if (state.failed) return retval; + if ( state.backtracking==0 ) { + ON171_tree = (Object)adaptor.create(ON171); + adaptor.addChild(root_0, ON171_tree); + } + + } + break; + case 9 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:808:11: WHERE + { + root_0 = (Object)adaptor.nil(); + + + WHERE172=(Token)match(input,WHERE,FOLLOW_WHERE_in_keyWord5395); if (state.failed) return retval; + if ( state.backtracking==0 ) { + WHERE172_tree = (Object)adaptor.create(WHERE172); + adaptor.addChild(root_0, WHERE172_tree); + } + + } + break; + case 10 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:809:11: OR + { + root_0 = (Object)adaptor.nil(); + + + OR173=(Token)match(input,OR,FOLLOW_OR_in_keyWord5407); if (state.failed) return retval; + if ( state.backtracking==0 ) { + OR173_tree = (Object)adaptor.create(OR173); + adaptor.addChild(root_0, OR173_tree); + } + + } + break; + case 11 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:810:11: AND + { + root_0 = (Object)adaptor.nil(); + + + AND174=(Token)match(input,AND,FOLLOW_AND_in_keyWord5419); if (state.failed) return retval; + if ( state.backtracking==0 ) { + AND174_tree = (Object)adaptor.create(AND174); + adaptor.addChild(root_0, AND174_tree); + } + + } + break; + case 12 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:811:11: NOT + { + root_0 = (Object)adaptor.nil(); + + + NOT175=(Token)match(input,NOT,FOLLOW_NOT_in_keyWord5431); if (state.failed) return retval; + if ( state.backtracking==0 ) { + NOT175_tree = (Object)adaptor.create(NOT175); + adaptor.addChild(root_0, NOT175_tree); + } + + } + break; + case 13 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:812:11: IN + { + root_0 = (Object)adaptor.nil(); + + + IN176=(Token)match(input,IN,FOLLOW_IN_in_keyWord5443); if (state.failed) return retval; + if ( state.backtracking==0 ) { + IN176_tree = (Object)adaptor.create(IN176); + adaptor.addChild(root_0, IN176_tree); + } + + } + break; + case 14 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:813:11: LIKE + { + root_0 = (Object)adaptor.nil(); + + + LIKE177=(Token)match(input,LIKE,FOLLOW_LIKE_in_keyWord5455); if (state.failed) return retval; + if ( state.backtracking==0 ) { + LIKE177_tree = (Object)adaptor.create(LIKE177); + adaptor.addChild(root_0, LIKE177_tree); + } + + } + break; + case 15 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:814:11: IS + { + root_0 = (Object)adaptor.nil(); + + + IS178=(Token)match(input,IS,FOLLOW_IS_in_keyWord5467); if (state.failed) return retval; + if ( state.backtracking==0 ) { + IS178_tree = (Object)adaptor.create(IS178); + adaptor.addChild(root_0, IS178_tree); + } + + } + break; + case 16 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:815:11: NULL + { + root_0 = (Object)adaptor.nil(); + + + NULL179=(Token)match(input,NULL,FOLLOW_NULL_in_keyWord5479); if (state.failed) return retval; + if ( state.backtracking==0 ) { + NULL179_tree = (Object)adaptor.create(NULL179); + adaptor.addChild(root_0, NULL179_tree); + } + + } + break; + case 17 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:816:11: ANY + { + root_0 = (Object)adaptor.nil(); + + + ANY180=(Token)match(input,ANY,FOLLOW_ANY_in_keyWord5491); if (state.failed) return retval; + if ( state.backtracking==0 ) { + ANY180_tree = (Object)adaptor.create(ANY180); + adaptor.addChild(root_0, ANY180_tree); + } + + } + break; + case 18 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:817:11: CONTAINS + { + root_0 = (Object)adaptor.nil(); + + + CONTAINS181=(Token)match(input,CONTAINS,FOLLOW_CONTAINS_in_keyWord5503); if (state.failed) return retval; + if ( state.backtracking==0 ) { + CONTAINS181_tree = (Object)adaptor.create(CONTAINS181); + adaptor.addChild(root_0, CONTAINS181_tree); + } + + } + break; + case 19 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:818:11: IN_FOLDER + { + root_0 = (Object)adaptor.nil(); + + + IN_FOLDER182=(Token)match(input,IN_FOLDER,FOLLOW_IN_FOLDER_in_keyWord5515); if (state.failed) return retval; + if ( state.backtracking==0 ) { + IN_FOLDER182_tree = (Object)adaptor.create(IN_FOLDER182); + adaptor.addChild(root_0, IN_FOLDER182_tree); + } + + } + break; + case 20 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:819:11: IN_TREE + { + root_0 = (Object)adaptor.nil(); + + + IN_TREE183=(Token)match(input,IN_TREE,FOLLOW_IN_TREE_in_keyWord5527); if (state.failed) return retval; + if ( state.backtracking==0 ) { + IN_TREE183_tree = (Object)adaptor.create(IN_TREE183); + adaptor.addChild(root_0, IN_TREE183_tree); + } + + } + break; + case 21 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:820:11: ORDER + { + root_0 = (Object)adaptor.nil(); + + + ORDER184=(Token)match(input,ORDER,FOLLOW_ORDER_in_keyWord5539); if (state.failed) return retval; + if ( state.backtracking==0 ) { + ORDER184_tree = (Object)adaptor.create(ORDER184); + adaptor.addChild(root_0, ORDER184_tree); + } + + } + break; + case 22 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:821:11: BY + { + root_0 = (Object)adaptor.nil(); + + + BY185=(Token)match(input,BY,FOLLOW_BY_in_keyWord5551); if (state.failed) return retval; + if ( state.backtracking==0 ) { + BY185_tree = (Object)adaptor.create(BY185); + adaptor.addChild(root_0, BY185_tree); + } + + } + break; + case 23 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:822:11: ASC + { + root_0 = (Object)adaptor.nil(); + + + ASC186=(Token)match(input,ASC,FOLLOW_ASC_in_keyWord5563); if (state.failed) return retval; + if ( state.backtracking==0 ) { + ASC186_tree = (Object)adaptor.create(ASC186); + adaptor.addChild(root_0, ASC186_tree); + } + + } + break; + case 24 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:823:11: DESC + { + root_0 = (Object)adaptor.nil(); + + + DESC187=(Token)match(input,DESC,FOLLOW_DESC_in_keyWord5575); if (state.failed) return retval; + if ( state.backtracking==0 ) { + DESC187_tree = (Object)adaptor.create(DESC187); + adaptor.addChild(root_0, DESC187_tree); + } + + } + break; + case 25 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:824:11: TIMESTAMP + { + root_0 = (Object)adaptor.nil(); + + + TIMESTAMP188=(Token)match(input,TIMESTAMP,FOLLOW_TIMESTAMP_in_keyWord5587); if (state.failed) return retval; + if ( state.backtracking==0 ) { + TIMESTAMP188_tree = (Object)adaptor.create(TIMESTAMP188); + adaptor.addChild(root_0, TIMESTAMP188_tree); + } + + } + break; + case 26 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:825:11: TRUE + { + root_0 = (Object)adaptor.nil(); + + + TRUE189=(Token)match(input,TRUE,FOLLOW_TRUE_in_keyWord5599); if (state.failed) return retval; + if ( state.backtracking==0 ) { + TRUE189_tree = (Object)adaptor.create(TRUE189); + adaptor.addChild(root_0, TRUE189_tree); + } + + } + break; + case 27 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:826:11: FALSE + { + root_0 = (Object)adaptor.nil(); + + + FALSE190=(Token)match(input,FALSE,FOLLOW_FALSE_in_keyWord5611); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FALSE190_tree = (Object)adaptor.create(FALSE190); + adaptor.addChild(root_0, FALSE190_tree); + } + + } + break; + case 28 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:827:11: cmisFunction + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_cmisFunction_in_keyWord5623); + cmisFunction191=cmisFunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, cmisFunction191.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "keyWord" + + + public static class cmisFunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "cmisFunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:830:1: cmisFunction : SCORE -> SCORE ; + public final CMISParser.cmisFunction_return cmisFunction() throws RecognitionException { + CMISParser.cmisFunction_return retval = new CMISParser.cmisFunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token SCORE192=null; + + Object SCORE192_tree=null; + RewriteRuleTokenStream stream_SCORE=new RewriteRuleTokenStream(adaptor,"token SCORE"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:831:9: ( SCORE -> SCORE ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:832:9: SCORE + { + SCORE192=(Token)match(input,SCORE,FOLLOW_SCORE_in_cmisFunction5656); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_SCORE.add(SCORE192); + + // AST REWRITE + // elements: SCORE + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 833:17: -> SCORE + { + adaptor.addChild(root_0, stream_SCORE.nextNode()); + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "cmisFunction" + + + public static class keyWordOrId_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "keyWordOrId" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:836:1: keyWordOrId : ( keyWord -> keyWord | ID -> ID ); + public final CMISParser.keyWordOrId_return keyWordOrId() throws RecognitionException { + CMISParser.keyWordOrId_return retval = new CMISParser.keyWordOrId_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token ID194=null; + ParserRuleReturnScope keyWord193 =null; + + Object ID194_tree=null; + RewriteRuleTokenStream stream_ID=new RewriteRuleTokenStream(adaptor,"token ID"); + RewriteRuleSubtreeStream stream_keyWord=new RewriteRuleSubtreeStream(adaptor,"rule keyWord"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:837:9: ( keyWord -> keyWord | ID -> ID ) + int alt46=2; + int LA46_0 = input.LA(1); + if ( ((LA46_0 >= AND && LA46_0 <= ASC)||LA46_0==BY||LA46_0==CONTAINS||LA46_0==DESC||LA46_0==FALSE||LA46_0==FROM||(LA46_0 >= IN && LA46_0 <= LEFT)||LA46_0==LIKE||LA46_0==NOT||LA46_0==NULL||(LA46_0 >= ON && LA46_0 <= OUTER)||(LA46_0 >= SCORE && LA46_0 <= SELECT)||(LA46_0 >= TIMESTAMP && LA46_0 <= WHERE)) ) { + alt46=1; + } + else if ( (LA46_0==ID) ) { + alt46=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 46, 0, input); + throw nvae; + } + + switch (alt46) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:838:9: keyWord + { + pushFollow(FOLLOW_keyWord_in_keyWordOrId5709); + keyWord193=keyWord(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_keyWord.add(keyWord193.getTree()); + // AST REWRITE + // elements: keyWord + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 839:17: -> keyWord + { + adaptor.addChild(root_0, stream_keyWord.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:840:11: ID + { + ID194=(Token)match(input,ID,FOLLOW_ID_in_keyWordOrId5741); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ID.add(ID194); + + // AST REWRITE + // elements: ID + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 841:17: -> ID + { + adaptor.addChild(root_0, stream_ID.nextNode()); + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw new CmisInvalidArgumentException(getErrorString(e), e); + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "keyWordOrId" + + // $ANTLR start synpred1_CMIS + public final void synpred1_CMIS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:388:9: ( tableName ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:388:10: tableName + { + pushFollow(FOLLOW_tableName_in_synpred1_CMIS1323); + tableName(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred1_CMIS + + // $ANTLR start synpred2_CMIS + public final void synpred2_CMIS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:484:9: ( LPAREN singleTable ( joinedTable )+ RPAREN ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:484:10: LPAREN singleTable ( joinedTable )+ RPAREN + { + match(input,LPAREN,FOLLOW_LPAREN_in_synpred2_CMIS1917); if (state.failed) return; + + pushFollow(FOLLOW_singleTable_in_synpred2_CMIS1919); + singleTable(); + state._fsp--; + if (state.failed) return; + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:484:29: ( joinedTable )+ + int cnt47=0; + loop47: + while (true) { + int alt47=2; + int LA47_0 = input.LA(1); + if ( (LA47_0==INNER||(LA47_0 >= JOIN && LA47_0 <= LEFT)) ) { + alt47=1; + } + + switch (alt47) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g:484:29: joinedTable + { + pushFollow(FOLLOW_joinedTable_in_synpred2_CMIS1921); + joinedTable(); + state._fsp--; + if (state.failed) return; + + } + break; + + default : + if ( cnt47 >= 1 ) break loop47; + if (state.backtracking>0) {state.failed=true; return;} + EarlyExitException eee = new EarlyExitException(47, input); + throw eee; + } + cnt47++; + } + + match(input,RPAREN,FOLLOW_RPAREN_in_synpred2_CMIS1924); if (state.failed) return; + + } + + } + // $ANTLR end synpred2_CMIS + + // Delegated rules + + public final boolean synpred2_CMIS() { + state.backtracking++; + int start = input.mark(); + try { + synpred2_CMIS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred1_CMIS() { + state.backtracking++; + int start = input.mark(); + try { + synpred1_CMIS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + + + protected DFA12 dfa12 = new DFA12(this); + protected DFA26 dfa26 = new DFA26(this); + protected DFA28 dfa28 = new DFA28(this); + protected DFA34 dfa34 = new DFA34(this); + protected DFA41 dfa41 = new DFA41(this); + static final String DFA12_eotS = + "\173\uffff"; + static final String DFA12_eofS = + "\173\uffff"; + static final String DFA12_minS = + "\1\5\1\61\1\uffff\2\13\1\5\5\13\1\110\1\33\1\0\1\33\1\0\35\33\5\0\2\13"+ + "\1\5\1\uffff\1\13\1\5\1\13\2\0\35\33\1\0\35\33\1\0\2\13\2\0"; + static final String DFA12_maxS = + "\1\127\1\61\1\uffff\2\126\1\127\5\126\1\110\1\45\1\0\1\45\1\0\35\33\5"+ + "\0\2\126\1\127\1\uffff\1\126\1\127\1\126\2\0\35\33\1\0\35\33\1\0\2\126"+ + "\2\0"; + static final String DFA12_acceptS = + "\2\uffff\1\2\62\uffff\1\1\105\uffff"; + static final String DFA12_specialS = + "\1\15\14\uffff\1\6\1\uffff\1\7\35\uffff\1\5\1\4\1\3\1\10\1\11\7\uffff"+ + "\1\12\1\13\35\uffff\1\14\35\uffff\1\2\2\uffff\1\1\1\0}>"; + static final String[] DFA12_transitionS = { + "\4\2\1\uffff\1\2\6\uffff\1\2\3\uffff\1\2\11\uffff\1\2\1\uffff\1\2\3\uffff"+ + "\10\2\2\uffff\1\2\5\uffff\1\2\1\uffff\1\2\1\uffff\4\2\15\uffff\1\1\1"+ + "\2\11\uffff\3\2", + "\1\3", + "", + "\1\14\7\uffff\1\7\7\uffff\1\5\3\uffff\1\12\1\6\4\uffff\1\4\42\uffff"+ + "\1\10\1\15\13\uffff\1\13\1\11", + "\1\14\7\uffff\1\7\4\uffff\1\16\2\uffff\1\5\3\uffff\1\12\1\6\4\uffff"+ + "\1\4\42\uffff\1\10\1\17\13\uffff\1\13\1\11", + "\1\32\1\40\1\21\1\46\1\uffff\1\45\6\uffff\1\41\3\uffff\1\47\11\uffff"+ + "\1\52\1\uffff\1\22\3\uffff\1\54\1\34\1\24\1\42\1\43\1\36\1\23\1\25\2"+ + "\uffff\1\35\5\uffff\1\33\1\uffff\1\37\1\uffff\1\27\1\31\1\44\1\26\15"+ + "\uffff\1\53\1\20\11\uffff\1\50\1\51\1\30", + "\1\14\7\uffff\1\7\7\uffff\1\5\3\uffff\1\12\1\6\4\uffff\1\4\42\uffff"+ + "\1\10\1\55\13\uffff\1\13\1\11", + "\1\14\7\uffff\1\7\7\uffff\1\5\3\uffff\1\12\1\6\4\uffff\1\4\42\uffff"+ + "\1\10\1\56\13\uffff\1\13\1\11", + "\1\14\7\uffff\1\7\7\uffff\1\5\3\uffff\1\12\1\6\4\uffff\1\4\42\uffff"+ + "\1\10\1\57\13\uffff\1\13\1\11", + "\1\14\7\uffff\1\7\7\uffff\1\5\3\uffff\1\12\1\6\4\uffff\1\4\42\uffff"+ + "\1\10\1\60\13\uffff\1\13\1\11", + "\1\14\7\uffff\1\7\7\uffff\1\5\3\uffff\1\12\1\6\4\uffff\1\4\42\uffff"+ + "\1\10\1\61\13\uffff\1\13\1\11", + "\1\62", + "\1\64\11\uffff\1\63", + "\1\uffff", + "\1\67\11\uffff\1\66", + "\1\uffff", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\70", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\14\7\uffff\1\7\7\uffff\1\5\3\uffff\1\12\1\6\4\uffff\1\4\42\uffff"+ + "\1\10\1\71\13\uffff\1\13\1\11", + "\1\14\7\uffff\1\7\7\uffff\1\5\3\uffff\1\12\1\6\4\uffff\1\4\42\uffff"+ + "\1\10\1\72\13\uffff\1\13\1\11", + "\1\105\1\113\1\74\1\121\1\uffff\1\120\6\uffff\1\114\3\uffff\1\122\11"+ + "\uffff\1\125\1\uffff\1\75\3\uffff\1\127\1\107\1\77\1\115\1\116\1\111"+ + "\1\76\1\100\2\uffff\1\110\5\uffff\1\106\1\uffff\1\112\1\uffff\1\102\1"+ + "\104\1\117\1\101\15\uffff\1\126\1\73\11\uffff\1\123\1\124\1\103", + "", + "\1\14\7\uffff\1\7\7\uffff\1\5\3\uffff\1\12\1\6\4\uffff\1\4\42\uffff"+ + "\1\10\1\130\13\uffff\1\13\1\11", + "\1\143\1\151\1\132\1\157\1\uffff\1\156\6\uffff\1\152\3\uffff\1\160\11"+ + "\uffff\1\163\1\uffff\1\133\3\uffff\1\165\1\145\1\135\1\153\1\154\1\147"+ + "\1\134\1\136\2\uffff\1\146\5\uffff\1\144\1\uffff\1\150\1\uffff\1\140"+ + "\1\142\1\155\1\137\15\uffff\1\164\1\131\11\uffff\1\161\1\162\1\141", + "\1\14\7\uffff\1\7\4\uffff\1\16\2\uffff\1\5\3\uffff\1\12\1\6\4\uffff"+ + "\1\4\42\uffff\1\10\1\166\13\uffff\1\13\1\11", + "\1\uffff", + "\1\uffff", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\167", + "\1\uffff", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\170", + "\1\uffff", + "\1\14\7\uffff\1\7\7\uffff\1\5\3\uffff\1\12\1\6\4\uffff\1\4\42\uffff"+ + "\1\10\1\171\13\uffff\1\13\1\11", + "\1\14\7\uffff\1\7\7\uffff\1\5\3\uffff\1\12\1\6\4\uffff\1\4\42\uffff"+ + "\1\10\1\172\13\uffff\1\13\1\11", + "\1\uffff", + "\1\uffff" + }; + + static final short[] DFA12_eot = DFA.unpackEncodedString(DFA12_eotS); + static final short[] DFA12_eof = DFA.unpackEncodedString(DFA12_eofS); + static final char[] DFA12_min = DFA.unpackEncodedStringToUnsignedChars(DFA12_minS); + static final char[] DFA12_max = DFA.unpackEncodedStringToUnsignedChars(DFA12_maxS); + static final short[] DFA12_accept = DFA.unpackEncodedString(DFA12_acceptS); + static final short[] DFA12_special = DFA.unpackEncodedString(DFA12_specialS); + static final short[][] DFA12_transition; + + static { + int numStates = DFA12_transitionS.length; + DFA12_transition = new short[numStates][]; + for (int i=0; i ^( FUNCTION $cmisFunctionName LPAREN ( functionArgument )* RPAREN ) |{...}? =>functionName= keyWordOrId LPAREN ( functionArgument )* RPAREN -> ^( FUNCTION $functionName LPAREN ( functionArgument )* RPAREN ) );"; + } + @Override + public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { + TokenStream input = (TokenStream)_input; + int _s = s; + switch ( s ) { + case 0 : + int LA12_122 = input.LA(1); + + int index12_122 = input.index(); + input.rewind(); + s = -1; + if ( (!(((strict == false)))) ) {s = 53;} + else if ( ((strict == false)) ) {s = 2;} + + input.seek(index12_122); + if ( s>=0 ) return s; + break; + + case 1 : + int LA12_121 = input.LA(1); + + int index12_121 = input.index(); + input.rewind(); + s = -1; + if ( (!(((strict == false)))) ) {s = 53;} + else if ( ((strict == false)) ) {s = 2;} + + input.seek(index12_121); + if ( s>=0 ) return s; + break; + + case 2 : + int LA12_118 = input.LA(1); + + int index12_118 = input.index(); + input.rewind(); + s = -1; + if ( (!(((strict == false)))) ) {s = 53;} + else if ( ((strict == false)) ) {s = 2;} + + input.seek(index12_118); + if ( s>=0 ) return s; + break; + + case 3 : + int LA12_47 = input.LA(1); + + int index12_47 = input.index(); + input.rewind(); + s = -1; + if ( (!(((strict == false)))) ) {s = 53;} + else if ( ((strict == false)) ) {s = 2;} + + input.seek(index12_47); + if ( s>=0 ) return s; + break; + + case 4 : + int LA12_46 = input.LA(1); + + int index12_46 = input.index(); + input.rewind(); + s = -1; + if ( (!(((strict == false)))) ) {s = 53;} + else if ( ((strict == false)) ) {s = 2;} + + input.seek(index12_46); + if ( s>=0 ) return s; + break; + + case 5 : + int LA12_45 = input.LA(1); + + int index12_45 = input.index(); + input.rewind(); + s = -1; + if ( (!(((strict == false)))) ) {s = 53;} + else if ( ((strict == false)) ) {s = 2;} + + input.seek(index12_45); + if ( s>=0 ) return s; + break; + + case 6 : + int LA12_13 = input.LA(1); + + int index12_13 = input.index(); + input.rewind(); + s = -1; + if ( (!(((strict == false)))) ) {s = 53;} + else if ( ((strict == false)) ) {s = 2;} + + input.seek(index12_13); + if ( s>=0 ) return s; + break; + + case 7 : + int LA12_15 = input.LA(1); + + int index12_15 = input.index(); + input.rewind(); + s = -1; + if ( (!(((strict == false)))) ) {s = 53;} + else if ( ((strict == false)) ) {s = 2;} + + input.seek(index12_15); + if ( s>=0 ) return s; + break; + + case 8 : + int LA12_48 = input.LA(1); + + int index12_48 = input.index(); + input.rewind(); + s = -1; + if ( (!(((strict == false)))) ) {s = 53;} + else if ( ((strict == false)) ) {s = 2;} + + input.seek(index12_48); + if ( s>=0 ) return s; + break; + + case 9 : + int LA12_49 = input.LA(1); + + int index12_49 = input.index(); + input.rewind(); + s = -1; + if ( (!(((strict == false)))) ) {s = 53;} + else if ( ((strict == false)) ) {s = 2;} + + input.seek(index12_49); + if ( s>=0 ) return s; + break; + + case 10 : + int LA12_57 = input.LA(1); + + int index12_57 = input.index(); + input.rewind(); + s = -1; + if ( (!(((strict == false)))) ) {s = 53;} + else if ( ((strict == false)) ) {s = 2;} + + input.seek(index12_57); + if ( s>=0 ) return s; + break; + + case 11 : + int LA12_58 = input.LA(1); + + int index12_58 = input.index(); + input.rewind(); + s = -1; + if ( (!(((strict == false)))) ) {s = 53;} + else if ( ((strict == false)) ) {s = 2;} + + input.seek(index12_58); + if ( s>=0 ) return s; + break; + + case 12 : + int LA12_88 = input.LA(1); + + int index12_88 = input.index(); + input.rewind(); + s = -1; + if ( (!(((strict == false)))) ) {s = 53;} + else if ( ((strict == false)) ) {s = 2;} + + input.seek(index12_88); + if ( s>=0 ) return s; + break; + + case 13 : + int LA12_0 = input.LA(1); + + int index12_0 = input.index(); + input.rewind(); + s = -1; + if ( (LA12_0==SCORE) ) {s = 1;} + else if ( ((LA12_0 >= AND && LA12_0 <= ASC)||LA12_0==BY||LA12_0==CONTAINS||LA12_0==DESC||LA12_0==FALSE||LA12_0==FROM||(LA12_0 >= ID && LA12_0 <= LEFT)||LA12_0==LIKE||LA12_0==NOT||LA12_0==NULL||(LA12_0 >= ON && LA12_0 <= OUTER)||LA12_0==SELECT||(LA12_0 >= TIMESTAMP && LA12_0 <= WHERE)) && ((strict == false))) {s = 2;} + + input.seek(index12_0); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 12, _s, input); + error(nvae); + throw nvae; + } + } + + static final String DFA26_eotS = + "\167\uffff"; + static final String DFA26_eofS = + "\167\uffff"; + static final String DFA26_minS = + "\2\5\12\uffff\1\5\1\13\1\5\1\61\5\13\1\33\1\uffff\36\33\2\13\1\5\1\13"+ + "\1\5\1\13\72\33\2\13"; + static final String DFA26_maxS = + "\2\127\12\uffff\1\127\1\126\1\127\1\110\5\126\1\45\1\uffff\1\45\35\33"+ + "\2\126\1\127\1\126\1\127\1\126\72\33\2\126"; + static final String DFA26_acceptS = + "\2\uffff\11\2\1\1\12\uffff\1\2\140\uffff"; + static final String DFA26_specialS = + "\1\4\13\uffff\1\7\1\15\2\uffff\1\12\1\13\1\3\1\5\1\1\40\uffff\1\0\1\10"+ + "\1\uffff\1\2\1\uffff\1\14\72\uffff\1\11\1\6}>"; + static final String[] DFA26_transitionS = { + "\1\5\1\6\1\5\1\7\1\uffff\1\7\1\11\5\uffff\1\6\1\uffff\1\10\1\uffff\1"+ + "\7\5\uffff\1\3\3\uffff\2\10\1\5\3\uffff\1\2\2\5\2\6\3\5\2\uffff\1\5\1"+ + "\uffff\1\12\3\uffff\1\1\1\uffff\1\5\1\uffff\2\5\1\7\1\5\13\uffff\1\10"+ + "\1\uffff\1\4\1\5\11\uffff\2\10\1\5", + "\4\13\1\uffff\2\13\5\uffff\1\13\1\uffff\1\13\1\uffff\1\13\5\uffff\1"+ + "\13\3\uffff\3\13\3\uffff\10\13\2\uffff\1\13\1\uffff\1\14\3\uffff\1\13"+ + "\1\uffff\1\13\1\uffff\4\13\13\uffff\1\13\1\uffff\2\13\11\uffff\3\13", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\4\13\1\uffff\1\13\1\25\5\uffff\1\13\1\uffff\1\23\1\uffff\1\13\5\uffff"+ + "\1\16\3\uffff\1\21\1\22\1\13\3\uffff\1\15\7\13\2\uffff\1\13\1\uffff\1"+ + "\13\3\uffff\1\13\1\uffff\1\13\1\uffff\4\13\13\uffff\1\24\1\26\2\13\11"+ + "\uffff\1\17\1\20\1\13", + "\1\26\7\uffff\1\26\4\uffff\1\27\2\uffff\1\26\1\uffff\1\13\1\uffff\2"+ + "\26\2\uffff\2\13\1\26\1\13\3\uffff\1\13\2\uffff\3\13\1\uffff\1\13\3\uffff"+ + "\2\13\21\uffff\2\26\13\uffff\2\26", + "\1\42\1\50\1\31\1\56\1\uffff\1\55\6\uffff\1\51\3\uffff\1\57\11\uffff"+ + "\1\62\1\uffff\1\32\3\uffff\1\64\1\44\1\34\1\52\1\53\1\46\1\33\1\35\2"+ + "\uffff\1\45\5\uffff\1\43\1\uffff\1\47\1\uffff\1\37\1\41\1\54\1\36\15"+ + "\uffff\1\63\1\30\11\uffff\1\60\1\61\1\40", + "\1\13\26\uffff\1\65", + "\1\26\7\uffff\1\26\7\uffff\1\26\1\uffff\1\13\1\uffff\2\26\2\uffff\2"+ + "\13\1\26\7\uffff\2\13\2\uffff\1\13\4\uffff\1\13\21\uffff\2\26\13\uffff"+ + "\2\26", + "\1\26\7\uffff\1\26\7\uffff\1\26\1\uffff\1\13\1\uffff\2\26\2\uffff\2"+ + "\13\1\26\7\uffff\2\13\2\uffff\1\13\4\uffff\1\13\21\uffff\2\26\13\uffff"+ + "\2\26", + "\1\26\7\uffff\1\26\7\uffff\1\26\1\uffff\1\13\1\uffff\2\26\2\uffff\2"+ + "\13\1\26\7\uffff\2\13\7\uffff\1\13\21\uffff\2\26\13\uffff\2\26", + "\1\26\7\uffff\1\26\7\uffff\1\26\1\uffff\1\13\1\uffff\2\26\2\uffff\2"+ + "\13\1\26\7\uffff\2\13\7\uffff\1\13\21\uffff\2\26\13\uffff\2\26", + "\1\26\7\uffff\1\26\7\uffff\1\26\1\uffff\1\13\1\uffff\2\26\2\uffff\2"+ + "\13\1\26\7\uffff\2\13\7\uffff\1\13\21\uffff\2\26\13\uffff\2\26", + "\1\67\11\uffff\1\66", + "", + "\1\71\11\uffff\1\70", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\72", + "\1\26\7\uffff\1\26\7\uffff\1\26\1\uffff\1\13\1\uffff\2\26\2\uffff\2"+ + "\13\1\26\7\uffff\2\13\7\uffff\1\13\21\uffff\2\26\13\uffff\2\26", + "\1\26\7\uffff\1\26\7\uffff\1\26\1\uffff\1\13\1\uffff\2\26\2\uffff\2"+ + "\13\1\26\7\uffff\2\13\7\uffff\1\13\21\uffff\2\26\13\uffff\2\26", + "\1\105\1\113\1\74\1\121\1\uffff\1\120\6\uffff\1\114\3\uffff\1\122\11"+ + "\uffff\1\125\1\uffff\1\75\3\uffff\1\127\1\107\1\77\1\115\1\116\1\111"+ + "\1\76\1\100\2\uffff\1\110\5\uffff\1\106\1\uffff\1\112\1\uffff\1\102\1"+ + "\104\1\117\1\101\15\uffff\1\126\1\73\11\uffff\1\123\1\124\1\103", + "\1\26\7\uffff\1\26\7\uffff\1\26\1\uffff\1\13\1\uffff\2\26\2\uffff\2"+ + "\13\1\26\1\13\3\uffff\1\13\2\uffff\3\13\5\uffff\2\13\21\uffff\2\26\13"+ + "\uffff\2\26", + "\1\142\1\150\1\131\1\156\1\uffff\1\155\6\uffff\1\151\3\uffff\1\157\11"+ + "\uffff\1\162\1\uffff\1\132\3\uffff\1\164\1\144\1\134\1\152\1\153\1\146"+ + "\1\133\1\135\2\uffff\1\145\5\uffff\1\143\1\uffff\1\147\1\uffff\1\137"+ + "\1\141\1\154\1\136\15\uffff\1\163\1\130\11\uffff\1\160\1\161\1\140", + "\1\26\7\uffff\1\26\4\uffff\1\27\2\uffff\1\26\1\uffff\1\13\1\uffff\2"+ + "\26\2\uffff\2\13\1\26\1\13\3\uffff\1\13\2\uffff\3\13\5\uffff\2\13\21"+ + "\uffff\2\26\13\uffff\2\26", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\165", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\166", + "\1\26\7\uffff\1\26\7\uffff\1\26\1\uffff\1\13\1\uffff\2\26\2\uffff\2"+ + "\13\1\26\7\uffff\2\13\7\uffff\1\13\21\uffff\2\26\13\uffff\2\26", + "\1\26\7\uffff\1\26\7\uffff\1\26\1\uffff\1\13\1\uffff\2\26\2\uffff\2"+ + "\13\1\26\1\13\3\uffff\1\13\2\uffff\3\13\5\uffff\2\13\21\uffff\2\26\13"+ + "\uffff\2\26" + }; + + static final short[] DFA26_eot = DFA.unpackEncodedString(DFA26_eotS); + static final short[] DFA26_eof = DFA.unpackEncodedString(DFA26_eofS); + static final char[] DFA26_min = DFA.unpackEncodedStringToUnsignedChars(DFA26_minS); + static final char[] DFA26_max = DFA.unpackEncodedStringToUnsignedChars(DFA26_maxS); + static final short[] DFA26_accept = DFA.unpackEncodedString(DFA26_acceptS); + static final short[] DFA26_special = DFA.unpackEncodedString(DFA26_specialS); + static final short[][] DFA26_transition; + + static { + int numStates = DFA26_transitionS.length; + DFA26_transition = new short[numStates][]; + for (int i=0; i ^( NEGATION searchTest ) | searchTest -> searchTest );"; + } + @Override + public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { + TokenStream input = (TokenStream)_input; + int _s = s; + switch ( s ) { + case 0 : + int LA26_53 = input.LA(1); + + int index26_53 = input.index(); + input.rewind(); + s = -1; + if ( (LA26_53==EQUALS||(LA26_53 >= GREATERTHAN && LA26_53 <= GREATERTHANOREQUALS)||(LA26_53 >= LESSTHAN && LA26_53 <= LESSTHANOREQUALS)||LA26_53==NOTEQUALS) ) {s = 11;} + else if ( (LA26_53==COLON||LA26_53==DECIMAL_INTEGER_LITERAL||LA26_53==DOUBLE_QUOTE||(LA26_53 >= FALSE && LA26_53 <= FLOATING_POINT_LITERAL)||LA26_53==ID||(LA26_53 >= QUOTED_STRING && LA26_53 <= RPAREN)||(LA26_53 >= TIMESTAMP && LA26_53 <= TRUE)) && ((strict == false))) {s = 22;} + + input.seek(index26_53); + if ( s>=0 ) return s; + break; + + case 1 : + int LA26_20 = input.LA(1); + + int index26_20 = input.index(); + input.rewind(); + s = -1; + if ( (LA26_20==EQUALS||(LA26_20 >= GREATERTHAN && LA26_20 <= GREATERTHANOREQUALS)||(LA26_20 >= LESSTHAN && LA26_20 <= LESSTHANOREQUALS)||LA26_20==NOTEQUALS) ) {s = 11;} + else if ( (LA26_20==COLON||LA26_20==DECIMAL_INTEGER_LITERAL||LA26_20==DOUBLE_QUOTE||(LA26_20 >= FALSE && LA26_20 <= FLOATING_POINT_LITERAL)||LA26_20==ID||(LA26_20 >= QUOTED_STRING && LA26_20 <= RPAREN)||(LA26_20 >= TIMESTAMP && LA26_20 <= TRUE)) && ((strict == false))) {s = 22;} + + input.seek(index26_20); + if ( s>=0 ) return s; + break; + + case 2 : + int LA26_56 = input.LA(1); + + int index26_56 = input.index(); + input.rewind(); + s = -1; + if ( (LA26_56==EQUALS||(LA26_56 >= GREATERTHAN && LA26_56 <= GREATERTHANOREQUALS)||LA26_56==IN||LA26_56==IS||(LA26_56 >= LESSTHAN && LA26_56 <= LIKE)||(LA26_56 >= NOT && LA26_56 <= NOTEQUALS)) ) {s = 11;} + else if ( (LA26_56==COLON||LA26_56==DECIMAL_INTEGER_LITERAL||LA26_56==DOUBLE_QUOTE||(LA26_56 >= FALSE && LA26_56 <= FLOATING_POINT_LITERAL)||LA26_56==ID||(LA26_56 >= QUOTED_STRING && LA26_56 <= RPAREN)||(LA26_56 >= TIMESTAMP && LA26_56 <= TRUE)) && ((strict == false))) {s = 22;} + + input.seek(index26_56); + if ( s>=0 ) return s; + break; + + case 3 : + int LA26_18 = input.LA(1); + + int index26_18 = input.index(); + input.rewind(); + s = -1; + if ( (LA26_18==EQUALS||(LA26_18 >= GREATERTHAN && LA26_18 <= GREATERTHANOREQUALS)||(LA26_18 >= LESSTHAN && LA26_18 <= LESSTHANOREQUALS)||LA26_18==NOTEQUALS) ) {s = 11;} + else if ( (LA26_18==COLON||LA26_18==DECIMAL_INTEGER_LITERAL||LA26_18==DOUBLE_QUOTE||(LA26_18 >= FALSE && LA26_18 <= FLOATING_POINT_LITERAL)||LA26_18==ID||(LA26_18 >= QUOTED_STRING && LA26_18 <= RPAREN)||(LA26_18 >= TIMESTAMP && LA26_18 <= TRUE)) && ((strict == false))) {s = 22;} + + input.seek(index26_18); + if ( s>=0 ) return s; + break; + + case 4 : + int LA26_0 = input.LA(1); + + int index26_0 = input.index(); + input.rewind(); + s = -1; + if ( (LA26_0==NOT) ) {s = 1;} + else if ( (LA26_0==ID) ) {s = 2;} + else if ( (LA26_0==DOUBLE_QUOTE) && ((strict == false))) {s = 3;} + else if ( (LA26_0==SCORE) ) {s = 4;} + else if ( (LA26_0==AND||LA26_0==AS||LA26_0==FROM||(LA26_0 >= IN && LA26_0 <= INNER)||(LA26_0 >= IS && LA26_0 <= LEFT)||LA26_0==LIKE||LA26_0==NULL||(LA26_0 >= ON && LA26_0 <= OR)||LA26_0==OUTER||LA26_0==SELECT||LA26_0==WHERE) && ((strict == false))) {s = 5;} + else if ( (LA26_0==ANY||LA26_0==CONTAINS||(LA26_0 >= IN_FOLDER && LA26_0 <= IN_TREE)) ) {s = 6;} + else if ( (LA26_0==ASC||LA26_0==BY||LA26_0==DESC||LA26_0==ORDER) && ((strict == false))) {s = 7;} + else if ( (LA26_0==DECIMAL_INTEGER_LITERAL||(LA26_0 >= FALSE && LA26_0 <= FLOATING_POINT_LITERAL)||LA26_0==QUOTED_STRING||(LA26_0 >= TIMESTAMP && LA26_0 <= TRUE)) ) {s = 8;} + else if ( (LA26_0==COLON) && ((strict == false))) {s = 9;} + else if ( (LA26_0==LPAREN) ) {s = 10;} + + input.seek(index26_0); + if ( s>=0 ) return s; + break; + + case 5 : + int LA26_19 = input.LA(1); + + int index26_19 = input.index(); + input.rewind(); + s = -1; + if ( (LA26_19==EQUALS||(LA26_19 >= GREATERTHAN && LA26_19 <= GREATERTHANOREQUALS)||(LA26_19 >= LESSTHAN && LA26_19 <= LESSTHANOREQUALS)||LA26_19==NOTEQUALS) ) {s = 11;} + else if ( (LA26_19==COLON||LA26_19==DECIMAL_INTEGER_LITERAL||LA26_19==DOUBLE_QUOTE||(LA26_19 >= FALSE && LA26_19 <= FLOATING_POINT_LITERAL)||LA26_19==ID||(LA26_19 >= QUOTED_STRING && LA26_19 <= RPAREN)||(LA26_19 >= TIMESTAMP && LA26_19 <= TRUE)) && ((strict == false))) {s = 22;} + + input.seek(index26_19); + if ( s>=0 ) return s; + break; + + case 6 : + int LA26_118 = input.LA(1); + + int index26_118 = input.index(); + input.rewind(); + s = -1; + if ( (LA26_118==EQUALS||(LA26_118 >= GREATERTHAN && LA26_118 <= GREATERTHANOREQUALS)||LA26_118==IN||LA26_118==IS||(LA26_118 >= LESSTHAN && LA26_118 <= LIKE)||(LA26_118 >= NOT && LA26_118 <= NOTEQUALS)) ) {s = 11;} + else if ( (LA26_118==COLON||LA26_118==DECIMAL_INTEGER_LITERAL||LA26_118==DOUBLE_QUOTE||(LA26_118 >= FALSE && LA26_118 <= FLOATING_POINT_LITERAL)||LA26_118==ID||(LA26_118 >= QUOTED_STRING && LA26_118 <= RPAREN)||(LA26_118 >= TIMESTAMP && LA26_118 <= TRUE)) && ((strict == false))) {s = 22;} + + input.seek(index26_118); + if ( s>=0 ) return s; + break; + + case 7 : + int LA26_12 = input.LA(1); + + int index26_12 = input.index(); + input.rewind(); + s = -1; + if ( ((LA26_12 >= AND && LA26_12 <= ASC)||LA26_12==BY||LA26_12==CONTAINS||LA26_12==DESC||LA26_12==FROM||(LA26_12 >= IN && LA26_12 <= LEFT)||LA26_12==LIKE||LA26_12==LPAREN||LA26_12==NOT||LA26_12==NULL||(LA26_12 >= ON && LA26_12 <= OUTER)||(LA26_12 >= SCORE && LA26_12 <= SELECT)||LA26_12==WHERE) ) {s = 11;} + else if ( (LA26_12==ID) ) {s = 13;} + else if ( (LA26_12==DOUBLE_QUOTE) ) {s = 14;} + else if ( (LA26_12==TIMESTAMP) ) {s = 15;} + else if ( (LA26_12==TRUE) ) {s = 16;} + else if ( (LA26_12==FALSE) ) {s = 17;} + else if ( (LA26_12==FLOATING_POINT_LITERAL) ) {s = 18;} + else if ( (LA26_12==DECIMAL_INTEGER_LITERAL) ) {s = 19;} + else if ( (LA26_12==QUOTED_STRING) ) {s = 20;} + else if ( (LA26_12==COLON) ) {s = 21;} + else if ( (LA26_12==RPAREN) && ((strict == false))) {s = 22;} + + input.seek(index26_12); + if ( s>=0 ) return s; + break; + + case 8 : + int LA26_54 = input.LA(1); + + int index26_54 = input.index(); + input.rewind(); + s = -1; + if ( (LA26_54==EQUALS||(LA26_54 >= GREATERTHAN && LA26_54 <= GREATERTHANOREQUALS)||(LA26_54 >= LESSTHAN && LA26_54 <= LESSTHANOREQUALS)||LA26_54==NOTEQUALS) ) {s = 11;} + else if ( (LA26_54==COLON||LA26_54==DECIMAL_INTEGER_LITERAL||LA26_54==DOUBLE_QUOTE||(LA26_54 >= FALSE && LA26_54 <= FLOATING_POINT_LITERAL)||LA26_54==ID||(LA26_54 >= QUOTED_STRING && LA26_54 <= RPAREN)||(LA26_54 >= TIMESTAMP && LA26_54 <= TRUE)) && ((strict == false))) {s = 22;} + + input.seek(index26_54); + if ( s>=0 ) return s; + break; + + case 9 : + int LA26_117 = input.LA(1); + + int index26_117 = input.index(); + input.rewind(); + s = -1; + if ( (LA26_117==EQUALS||(LA26_117 >= GREATERTHAN && LA26_117 <= GREATERTHANOREQUALS)||(LA26_117 >= LESSTHAN && LA26_117 <= LESSTHANOREQUALS)||LA26_117==NOTEQUALS) ) {s = 11;} + else if ( (LA26_117==COLON||LA26_117==DECIMAL_INTEGER_LITERAL||LA26_117==DOUBLE_QUOTE||(LA26_117 >= FALSE && LA26_117 <= FLOATING_POINT_LITERAL)||LA26_117==ID||(LA26_117 >= QUOTED_STRING && LA26_117 <= RPAREN)||(LA26_117 >= TIMESTAMP && LA26_117 <= TRUE)) && ((strict == false))) {s = 22;} + + input.seek(index26_117); + if ( s>=0 ) return s; + break; + + case 10 : + int LA26_16 = input.LA(1); + + int index26_16 = input.index(); + input.rewind(); + s = -1; + if ( (LA26_16==EQUALS||(LA26_16 >= GREATERTHAN && LA26_16 <= GREATERTHANOREQUALS)||(LA26_16 >= LESSTHAN && LA26_16 <= LESSTHANOREQUALS)||LA26_16==LPAREN||LA26_16==NOTEQUALS) ) {s = 11;} + else if ( (LA26_16==COLON||LA26_16==DECIMAL_INTEGER_LITERAL||LA26_16==DOUBLE_QUOTE||(LA26_16 >= FALSE && LA26_16 <= FLOATING_POINT_LITERAL)||LA26_16==ID||(LA26_16 >= QUOTED_STRING && LA26_16 <= RPAREN)||(LA26_16 >= TIMESTAMP && LA26_16 <= TRUE)) && ((strict == false))) {s = 22;} + + input.seek(index26_16); + if ( s>=0 ) return s; + break; + + case 11 : + int LA26_17 = input.LA(1); + + int index26_17 = input.index(); + input.rewind(); + s = -1; + if ( (LA26_17==EQUALS||(LA26_17 >= GREATERTHAN && LA26_17 <= GREATERTHANOREQUALS)||(LA26_17 >= LESSTHAN && LA26_17 <= LESSTHANOREQUALS)||LA26_17==LPAREN||LA26_17==NOTEQUALS) ) {s = 11;} + else if ( (LA26_17==COLON||LA26_17==DECIMAL_INTEGER_LITERAL||LA26_17==DOUBLE_QUOTE||(LA26_17 >= FALSE && LA26_17 <= FLOATING_POINT_LITERAL)||LA26_17==ID||(LA26_17 >= QUOTED_STRING && LA26_17 <= RPAREN)||(LA26_17 >= TIMESTAMP && LA26_17 <= TRUE)) && ((strict == false))) {s = 22;} + + input.seek(index26_17); + if ( s>=0 ) return s; + break; + + case 12 : + int LA26_58 = input.LA(1); + + int index26_58 = input.index(); + input.rewind(); + s = -1; + if ( (LA26_58==DOT) ) {s = 23;} + else if ( (LA26_58==EQUALS||(LA26_58 >= GREATERTHAN && LA26_58 <= GREATERTHANOREQUALS)||LA26_58==IN||LA26_58==IS||(LA26_58 >= LESSTHAN && LA26_58 <= LIKE)||(LA26_58 >= NOT && LA26_58 <= NOTEQUALS)) ) {s = 11;} + else if ( (LA26_58==COLON||LA26_58==DECIMAL_INTEGER_LITERAL||LA26_58==DOUBLE_QUOTE||(LA26_58 >= FALSE && LA26_58 <= FLOATING_POINT_LITERAL)||LA26_58==ID||(LA26_58 >= QUOTED_STRING && LA26_58 <= RPAREN)||(LA26_58 >= TIMESTAMP && LA26_58 <= TRUE)) && ((strict == false))) {s = 22;} + + input.seek(index26_58); + if ( s>=0 ) return s; + break; + + case 13 : + int LA26_13 = input.LA(1); + + int index26_13 = input.index(); + input.rewind(); + s = -1; + if ( (LA26_13==DOT) ) {s = 23;} + else if ( (LA26_13==EQUALS||(LA26_13 >= GREATERTHAN && LA26_13 <= GREATERTHANOREQUALS)||LA26_13==IN||LA26_13==IS||(LA26_13 >= LESSTHAN && LA26_13 <= LIKE)||LA26_13==LPAREN||(LA26_13 >= NOT && LA26_13 <= NOTEQUALS)) ) {s = 11;} + else if ( (LA26_13==COLON||LA26_13==DECIMAL_INTEGER_LITERAL||LA26_13==DOUBLE_QUOTE||(LA26_13 >= FALSE && LA26_13 <= FLOATING_POINT_LITERAL)||LA26_13==ID||(LA26_13 >= QUOTED_STRING && LA26_13 <= RPAREN)||(LA26_13 >= TIMESTAMP && LA26_13 <= TRUE)) && ((strict == false))) {s = 22;} + + input.seek(index26_13); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 26, _s, input); + error(nvae); + throw nvae; + } + } + + static final String DFA28_eotS = + "\u00e5\uffff"; + static final String DFA28_eofS = + "\u0083\uffff\1\145\36\uffff\1\u0084\35\uffff\1\u0084\44\uffff"; + static final String DFA28_minS = + "\1\5\1\30\1\5\2\uffff\1\33\4\61\2\35\2\uffff\1\33\2\uffff\1\46\3\uffff"+ + "\35\33\1\uffff\3\13\1\uffff\1\35\1\5\1\30\1\13\1\5\2\13\1\5\2\13\1\5\1"+ + "\13\36\33\1\46\4\uffff\35\33\1\5\1\uffff\35\33\1\5\35\33\1\5\2\35\1\5"+ + "\3\13\35\33\1\35"; + static final String DFA28_maxS = + "\1\127\1\66\1\127\2\uffff\4\61\1\110\2\66\2\uffff\1\45\2\uffff\1\57\3"+ + "\uffff\35\33\1\uffff\3\126\1\uffff\1\66\1\127\1\66\1\126\1\127\2\126\1"+ + "\127\2\126\1\127\1\126\35\33\1\45\1\57\4\uffff\35\33\1\111\1\uffff\35"+ + "\33\1\111\35\33\1\111\2\66\1\127\3\126\35\33\1\66"; + static final String DFA28_acceptS = + "\3\uffff\2\1\7\uffff\2\5\1\uffff\2\1\1\uffff\1\2\1\3\1\4\35\uffff\1\6"+ + "\3\uffff\1\5\53\uffff\1\2\1\3\1\4\1\7\36\uffff\1\10\140\uffff"; + static final String DFA28_specialS = + "\1\42\1\102\1\72\2\uffff\1\2\3\uffff\1\51\1\12\1\14\11\uffff\1\104\1\112"+ + "\1\117\1\124\1\106\1\113\1\73\1\75\1\50\1\56\1\34\1\43\1\20\1\25\1\10"+ + "\1\5\1\13\1\0\1\4\1\125\1\121\1\114\1\105\1\76\1\70\1\57\1\47\1\67\1\115"+ + "\1\uffff\1\120\1\40\1\37\3\uffff\1\123\1\1\1\uffff\1\64\1\27\1\uffff\1"+ + "\7\1\26\1\uffff\1\6\35\uffff\1\60\1\62\41\uffff\1\122\36\uffff\1\22\35"+ + "\uffff\1\32\1\uffff\1\53\1\3\1\31\1\24\1\23\1\21\1\17\1\16\1\15\1\44\1"+ + "\41\1\36\1\35\1\33\1\30\1\55\1\61\1\63\1\45\1\46\1\52\1\54\1\77\1\100"+ + "\1\101\1\66\1\71\1\74\1\110\1\107\1\111\1\103\1\116\1\11\1\65}>"; + static final String[] DFA28_transitionS = { + "\1\4\1\5\2\4\1\uffff\1\4\1\15\5\uffff\1\6\1\uffff\1\14\1\uffff\1\4\5"+ + "\uffff\1\2\3\uffff\1\13\1\14\1\4\3\uffff\1\1\2\4\1\7\1\10\3\4\2\uffff"+ + "\1\4\5\uffff\1\4\1\uffff\1\4\1\uffff\4\4\13\uffff\1\14\1\uffff\1\3\1"+ + "\4\11\uffff\1\11\1\12\1\4", + "\1\16\4\uffff\1\17\5\uffff\2\17\1\uffff\1\22\3\uffff\1\24\2\uffff\2"+ + "\17\1\23\1\uffff\1\20\3\uffff\1\21\1\17", + "\1\37\1\45\1\26\1\53\1\uffff\1\52\6\uffff\1\46\3\uffff\1\54\11\uffff"+ + "\1\57\1\uffff\1\27\3\uffff\1\61\1\41\1\31\1\47\1\50\1\43\1\30\1\32\2"+ + "\uffff\1\42\5\uffff\1\40\1\uffff\1\44\1\uffff\1\34\1\36\1\51\1\33\15"+ + "\uffff\1\60\1\25\11\uffff\1\55\1\56\1\35", + "", + "", + "\1\62\11\uffff\1\62\13\uffff\1\20", + "\1\63", + "\1\64", + "\1\65", + "\1\20\26\uffff\1\66", + "\1\66\5\uffff\2\66\10\uffff\2\66\2\uffff\1\20\4\uffff\1\66", + "\1\66\5\uffff\2\66\10\uffff\2\66\2\uffff\1\20\4\uffff\1\66", + "", + "", + "\1\70\11\uffff\1\67", + "", + "", + "\1\22\10\uffff\1\23", + "", + "", + "", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "\1\71", + "", + "\1\20\7\uffff\1\20\7\uffff\1\73\3\uffff\2\20\4\uffff\1\72\42\uffff\1"+ + "\74\1\20\13\uffff\2\20", + "\1\20\7\uffff\1\20\7\uffff\1\76\3\uffff\2\20\4\uffff\1\75\42\uffff\1"+ + "\77\1\20\13\uffff\2\20", + "\1\20\7\uffff\1\20\7\uffff\1\101\3\uffff\2\20\4\uffff\1\100\42\uffff"+ + "\1\102\1\20\13\uffff\2\20", + "", + "\1\17\5\uffff\2\17\1\uffff\1\22\3\uffff\1\24\2\uffff\2\17\1\23\5\uffff"+ + "\1\21\1\17", + "\1\115\1\123\1\104\1\131\1\uffff\1\130\6\uffff\1\124\3\uffff\1\132\11"+ + "\uffff\1\135\1\uffff\1\105\3\uffff\1\137\1\117\1\107\1\125\1\126\1\121"+ + "\1\106\1\110\2\uffff\1\120\5\uffff\1\116\1\uffff\1\122\1\uffff\1\112"+ + "\1\114\1\127\1\111\15\uffff\1\136\1\103\11\uffff\1\133\1\134\1\113", + "\1\140\4\uffff\1\20\5\uffff\2\20\1\uffff\1\142\3\uffff\1\144\2\uffff"+ + "\2\20\1\143\5\uffff\1\141\1\20", + "\1\20\3\uffff\1\145\3\uffff\1\20\4\uffff\1\20\2\uffff\1\20\3\uffff\2"+ + "\20\4\uffff\1\20\42\uffff\2\20\13\uffff\2\20", + "\1\160\1\166\1\147\1\174\1\uffff\1\173\6\uffff\1\167\3\uffff\1\175\11"+ + "\uffff\1\u0080\1\uffff\1\150\3\uffff\1\u0082\1\162\1\152\1\170\1\171"+ + "\1\164\1\151\1\153\2\uffff\1\163\5\uffff\1\161\1\uffff\1\165\1\uffff"+ + "\1\155\1\157\1\172\1\154\15\uffff\1\u0081\1\146\11\uffff\1\176\1\177"+ + "\1\156", + "\1\20\7\uffff\1\20\7\uffff\1\20\3\uffff\2\20\4\uffff\1\20\42\uffff\1"+ + "\20\1\u0083\13\uffff\2\20", + "\1\20\3\uffff\1\u0084\3\uffff\1\20\4\uffff\1\20\2\uffff\1\20\3\uffff"+ + "\2\20\4\uffff\1\20\42\uffff\2\20\13\uffff\2\20", + "\1\u008f\1\u0095\1\u0086\1\u009b\1\uffff\1\u009a\6\uffff\1\u0096\3\uffff"+ + "\1\u009c\11\uffff\1\u009f\1\uffff\1\u0087\3\uffff\1\u00a1\1\u0091\1\u0089"+ + "\1\u0097\1\u0098\1\u0093\1\u0088\1\u008a\2\uffff\1\u0092\5\uffff\1\u0090"+ + "\1\uffff\1\u0094\1\uffff\1\u008c\1\u008e\1\u0099\1\u008b\15\uffff\1\u00a0"+ + "\1\u0085\11\uffff\1\u009d\1\u009e\1\u008d", + "\1\20\7\uffff\1\20\7\uffff\1\20\3\uffff\2\20\4\uffff\1\20\42\uffff\1"+ + "\20\1\u00a2\13\uffff\2\20", + "\1\20\3\uffff\1\u0084\3\uffff\1\20\4\uffff\1\20\2\uffff\1\20\3\uffff"+ + "\2\20\4\uffff\1\20\42\uffff\2\20\13\uffff\2\20", + "\1\u00ad\1\u00b3\1\u00a4\1\u00b9\1\uffff\1\u00b8\6\uffff\1\u00b4\3\uffff"+ + "\1\u00ba\11\uffff\1\u00bd\1\uffff\1\u00a5\3\uffff\1\u00bf\1\u00af\1\u00a7"+ + "\1\u00b5\1\u00b6\1\u00b1\1\u00a6\1\u00a8\2\uffff\1\u00b0\5\uffff\1\u00ae"+ + "\1\uffff\1\u00b2\1\uffff\1\u00aa\1\u00ac\1\u00b7\1\u00a9\15\uffff\1\u00be"+ + "\1\u00a3\11\uffff\1\u00bb\1\u00bc\1\u00ab", + "\1\20\7\uffff\1\20\7\uffff\1\20\3\uffff\2\20\4\uffff\1\20\42\uffff\1"+ + "\20\1\u00c0\13\uffff\2\20", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c1", + "\1\u00c3\11\uffff\1\u00c2", + "\1\142\10\uffff\1\143", + "", + "", + "", + "", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\u00c4", + "\1\145\27\uffff\1\20\5\uffff\2\20\10\uffff\2\20\7\uffff\1\20\3\uffff"+ + "\2\145\15\uffff\1\145", + "", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u00c5", + "\1\u0084\27\uffff\1\20\5\uffff\2\20\10\uffff\2\20\7\uffff\1\20\3\uffff"+ + "\2\u0084\15\uffff\1\u0084", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u00c6", + "\1\u0084\27\uffff\1\20\5\uffff\2\20\10\uffff\2\20\7\uffff\1\20\3\uffff"+ + "\2\u0084\15\uffff\1\u0084", + "\1\17\5\uffff\2\17\1\uffff\1\22\3\uffff\1\24\2\uffff\2\17\1\23\5\uffff"+ + "\1\21\1\17", + "\1\20\5\uffff\2\20\1\uffff\1\142\3\uffff\1\144\2\uffff\2\20\1\143\5"+ + "\uffff\1\141\1\20", + "\1\u00d1\1\u00d7\1\u00c8\1\u00dd\1\uffff\1\u00dc\6\uffff\1\u00d8\3\uffff"+ + "\1\u00de\11\uffff\1\u00e1\1\uffff\1\u00c9\3\uffff\1\u00e3\1\u00d3\1\u00cb"+ + "\1\u00d9\1\u00da\1\u00d5\1\u00ca\1\u00cc\2\uffff\1\u00d4\5\uffff\1\u00d2"+ + "\1\uffff\1\u00d6\1\uffff\1\u00ce\1\u00d0\1\u00db\1\u00cd\15\uffff\1\u00e2"+ + "\1\u00c7\11\uffff\1\u00df\1\u00e0\1\u00cf", + "\1\20\3\uffff\1\145\3\uffff\1\20\4\uffff\1\20\2\uffff\1\20\3\uffff\2"+ + "\20\4\uffff\1\20\42\uffff\2\20\13\uffff\2\20", + "\1\20\3\uffff\1\u0084\3\uffff\1\20\4\uffff\1\20\2\uffff\1\20\3\uffff"+ + "\2\20\4\uffff\1\20\42\uffff\2\20\13\uffff\2\20", + "\1\20\3\uffff\1\u0084\3\uffff\1\20\4\uffff\1\20\2\uffff\1\20\3\uffff"+ + "\2\20\4\uffff\1\20\42\uffff\2\20\13\uffff\2\20", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\u00e4", + "\1\20\5\uffff\2\20\1\uffff\1\142\3\uffff\1\144\2\uffff\2\20\1\143\5"+ + "\uffff\1\141\1\20" + }; + + static final short[] DFA28_eot = DFA.unpackEncodedString(DFA28_eotS); + static final short[] DFA28_eof = DFA.unpackEncodedString(DFA28_eofS); + static final char[] DFA28_min = DFA.unpackEncodedStringToUnsignedChars(DFA28_minS); + static final char[] DFA28_max = DFA.unpackEncodedStringToUnsignedChars(DFA28_maxS); + static final short[] DFA28_accept = DFA.unpackEncodedString(DFA28_acceptS); + static final short[] DFA28_special = DFA.unpackEncodedString(DFA28_specialS); + static final short[][] DFA28_transition; + + static { + int numStates = DFA28_transitionS.length; + DFA28_transition = new short[numStates][]; + for (int i=0; i=0 ) return s; + break; + + case 1 : + int LA28_58 = input.LA(1); + + int index28_58 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_58==COMMA) ) {s = 101;} + else if ( (LA28_58==COLON||LA28_58==DECIMAL_INTEGER_LITERAL||LA28_58==DOT||LA28_58==DOUBLE_QUOTE||(LA28_58 >= FALSE && LA28_58 <= FLOATING_POINT_LITERAL)||LA28_58==ID||(LA28_58 >= QUOTED_STRING && LA28_58 <= RPAREN)||(LA28_58 >= TIMESTAMP && LA28_58 <= TRUE)) && ((strict == false))) {s = 16;} + + input.seek(index28_58); + if ( s>=0 ) return s; + break; + + case 2 : + int LA28_5 = input.LA(1); + + int index28_5 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_5==LPAREN) && ((strict == false))) {s = 16;} + else if ( (LA28_5==DOUBLE_QUOTE||LA28_5==ID) ) {s = 50;} + + input.seek(index28_5); + if ( s>=0 ) return s; + break; + + case 3 : + int LA28_195 = input.LA(1); + + int index28_195 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_195==SELECT) && ((strict == false))) {s = 199;} + else if ( (LA28_195==AS) && ((strict == false))) {s = 200;} + else if ( (LA28_195==FROM) && ((strict == false))) {s = 201;} + else if ( (LA28_195==JOIN) && ((strict == false))) {s = 202;} + else if ( (LA28_195==INNER) && ((strict == false))) {s = 203;} + else if ( (LA28_195==LEFT) && ((strict == false))) {s = 204;} + else if ( (LA28_195==OUTER) && ((strict == false))) {s = 205;} + else if ( (LA28_195==ON) && ((strict == false))) {s = 206;} + else if ( (LA28_195==WHERE) && ((strict == false))) {s = 207;} + else if ( (LA28_195==OR) && ((strict == false))) {s = 208;} + else if ( (LA28_195==AND) && ((strict == false))) {s = 209;} + else if ( (LA28_195==NOT) && ((strict == false))) {s = 210;} + else if ( (LA28_195==IN) && ((strict == false))) {s = 211;} + else if ( (LA28_195==LIKE) && ((strict == false))) {s = 212;} + else if ( (LA28_195==IS) && ((strict == false))) {s = 213;} + else if ( (LA28_195==NULL) && ((strict == false))) {s = 214;} + else if ( (LA28_195==ANY) && ((strict == false))) {s = 215;} + else if ( (LA28_195==CONTAINS) && ((strict == false))) {s = 216;} + else if ( (LA28_195==IN_FOLDER) && ((strict == false))) {s = 217;} + else if ( (LA28_195==IN_TREE) && ((strict == false))) {s = 218;} + else if ( (LA28_195==ORDER) && ((strict == false))) {s = 219;} + else if ( (LA28_195==BY) && ((strict == false))) {s = 220;} + else if ( (LA28_195==ASC) && ((strict == false))) {s = 221;} + else if ( (LA28_195==DESC) && ((strict == false))) {s = 222;} + else if ( (LA28_195==TIMESTAMP) && ((strict == false))) {s = 223;} + else if ( (LA28_195==TRUE) && ((strict == false))) {s = 224;} + else if ( (LA28_195==FALSE) && ((strict == false))) {s = 225;} + else if ( (LA28_195==SCORE) && ((strict == false))) {s = 226;} + else if ( (LA28_195==ID) && ((strict == false))) {s = 227;} + + input.seek(index28_195); + if ( s>=0 ) return s; + break; + + case 4 : + int LA28_39 = input.LA(1); + + int index28_39 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_39==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_39); + if ( s>=0 ) return s; + break; + + case 5 : + int LA28_36 = input.LA(1); + + int index28_36 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_36==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_36); + if ( s>=0 ) return s; + break; + + case 6 : + int LA28_66 = input.LA(1); + + int index28_66 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_66==RPAREN) ) {s = 192;} + else if ( (LA28_66==COLON||LA28_66==DECIMAL_INTEGER_LITERAL||LA28_66==DOUBLE_QUOTE||(LA28_66 >= FALSE && LA28_66 <= FLOATING_POINT_LITERAL)||LA28_66==ID||LA28_66==QUOTED_STRING||(LA28_66 >= TIMESTAMP && LA28_66 <= TRUE)) && ((strict == false))) {s = 16;} + + input.seek(index28_66); + if ( s>=0 ) return s; + break; + + case 7 : + int LA28_63 = input.LA(1); + + int index28_63 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_63==RPAREN) ) {s = 162;} + else if ( (LA28_63==COLON||LA28_63==DECIMAL_INTEGER_LITERAL||LA28_63==DOUBLE_QUOTE||(LA28_63 >= FALSE && LA28_63 <= FLOATING_POINT_LITERAL)||LA28_63==ID||LA28_63==QUOTED_STRING||(LA28_63 >= TIMESTAMP && LA28_63 <= TRUE)) && ((strict == false))) {s = 16;} + + input.seek(index28_63); + if ( s>=0 ) return s; + break; + + case 8 : + int LA28_35 = input.LA(1); + + int index28_35 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_35==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_35); + if ( s>=0 ) return s; + break; + + case 9 : + int LA28_227 = input.LA(1); + + int index28_227 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_227==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_227); + if ( s>=0 ) return s; + break; + + case 10 : + int LA28_10 = input.LA(1); + + int index28_10 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_10==LPAREN) && ((strict == false))) {s = 16;} + else if ( (LA28_10==EQUALS||(LA28_10 >= GREATERTHAN && LA28_10 <= GREATERTHANOREQUALS)||(LA28_10 >= LESSTHAN && LA28_10 <= LESSTHANOREQUALS)||LA28_10==NOTEQUALS) ) {s = 54;} + + input.seek(index28_10); + if ( s>=0 ) return s; + break; + + case 11 : + int LA28_37 = input.LA(1); + + int index28_37 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_37==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_37); + if ( s>=0 ) return s; + break; + + case 12 : + int LA28_11 = input.LA(1); + + int index28_11 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_11==LPAREN) && ((strict == false))) {s = 16;} + else if ( (LA28_11==EQUALS||(LA28_11 >= GREATERTHAN && LA28_11 <= GREATERTHANOREQUALS)||(LA28_11 >= LESSTHAN && LA28_11 <= LESSTHANOREQUALS)||LA28_11==NOTEQUALS) ) {s = 54;} + + input.seek(index28_11); + if ( s>=0 ) return s; + break; + + case 13 : + int LA28_202 = input.LA(1); + + int index28_202 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_202==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_202); + if ( s>=0 ) return s; + break; + + case 14 : + int LA28_201 = input.LA(1); + + int index28_201 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_201==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_201); + if ( s>=0 ) return s; + break; + + case 15 : + int LA28_200 = input.LA(1); + + int index28_200 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_200==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_200); + if ( s>=0 ) return s; + break; + + case 16 : + int LA28_33 = input.LA(1); + + int index28_33 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_33==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_33); + if ( s>=0 ) return s; + break; + + case 17 : + int LA28_199 = input.LA(1); + + int index28_199 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_199==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_199); + if ( s>=0 ) return s; + break; + + case 18 : + int LA28_162 = input.LA(1); + + int index28_162 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_162==EQUALS||(LA28_162 >= GREATERTHAN && LA28_162 <= GREATERTHANOREQUALS)||(LA28_162 >= LESSTHAN && LA28_162 <= LESSTHANOREQUALS)||LA28_162==NOTEQUALS) && ((strict == false))) {s = 16;} + else if ( (LA28_162==EOF||LA28_162==AND||(LA28_162 >= OR && LA28_162 <= ORDER)||LA28_162==RPAREN) ) {s = 132;} + + input.seek(index28_162); + if ( s>=0 ) return s; + break; + + case 19 : + int LA28_198 = input.LA(1); + + int index28_198 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_198==COLON||LA28_198==DECIMAL_INTEGER_LITERAL||LA28_198==DOT||LA28_198==DOUBLE_QUOTE||(LA28_198 >= FALSE && LA28_198 <= FLOATING_POINT_LITERAL)||LA28_198==ID||(LA28_198 >= QUOTED_STRING && LA28_198 <= RPAREN)||(LA28_198 >= TIMESTAMP && LA28_198 <= TRUE)) && ((strict == false))) {s = 16;} + else if ( (LA28_198==COMMA) ) {s = 132;} + + input.seek(index28_198); + if ( s>=0 ) return s; + break; + + case 20 : + int LA28_197 = input.LA(1); + + int index28_197 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_197==COLON||LA28_197==DECIMAL_INTEGER_LITERAL||LA28_197==DOT||LA28_197==DOUBLE_QUOTE||(LA28_197 >= FALSE && LA28_197 <= FLOATING_POINT_LITERAL)||LA28_197==ID||(LA28_197 >= QUOTED_STRING && LA28_197 <= RPAREN)||(LA28_197 >= TIMESTAMP && LA28_197 <= TRUE)) && ((strict == false))) {s = 16;} + else if ( (LA28_197==COMMA) ) {s = 132;} + + input.seek(index28_197); + if ( s>=0 ) return s; + break; + + case 21 : + int LA28_34 = input.LA(1); + + int index28_34 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_34==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_34); + if ( s>=0 ) return s; + break; + + case 22 : + int LA28_64 = input.LA(1); + + int index28_64 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_64==COLON||LA28_64==DECIMAL_INTEGER_LITERAL||LA28_64==DOT||LA28_64==DOUBLE_QUOTE||(LA28_64 >= FALSE && LA28_64 <= FLOATING_POINT_LITERAL)||LA28_64==ID||(LA28_64 >= QUOTED_STRING && LA28_64 <= RPAREN)||(LA28_64 >= TIMESTAMP && LA28_64 <= TRUE)) && ((strict == false))) {s = 16;} + else if ( (LA28_64==COMMA) ) {s = 132;} + + input.seek(index28_64); + if ( s>=0 ) return s; + break; + + case 23 : + int LA28_61 = input.LA(1); + + int index28_61 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_61==COLON||LA28_61==DECIMAL_INTEGER_LITERAL||LA28_61==DOT||LA28_61==DOUBLE_QUOTE||(LA28_61 >= FALSE && LA28_61 <= FLOATING_POINT_LITERAL)||LA28_61==ID||(LA28_61 >= QUOTED_STRING && LA28_61 <= RPAREN)||(LA28_61 >= TIMESTAMP && LA28_61 <= TRUE)) && ((strict == false))) {s = 16;} + else if ( (LA28_61==COMMA) ) {s = 132;} + + input.seek(index28_61); + if ( s>=0 ) return s; + break; + + case 24 : + int LA28_208 = input.LA(1); + + int index28_208 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_208==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_208); + if ( s>=0 ) return s; + break; + + case 25 : + int LA28_196 = input.LA(1); + + int index28_196 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_196==COMMA) ) {s = 101;} + else if ( (LA28_196==COLON||LA28_196==DECIMAL_INTEGER_LITERAL||LA28_196==DOT||LA28_196==DOUBLE_QUOTE||(LA28_196 >= FALSE && LA28_196 <= FLOATING_POINT_LITERAL)||LA28_196==ID||(LA28_196 >= QUOTED_STRING && LA28_196 <= RPAREN)||(LA28_196 >= TIMESTAMP && LA28_196 <= TRUE)) && ((strict == false))) {s = 16;} + + input.seek(index28_196); + if ( s>=0 ) return s; + break; + + case 26 : + int LA28_192 = input.LA(1); + + int index28_192 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_192==EQUALS||(LA28_192 >= GREATERTHAN && LA28_192 <= GREATERTHANOREQUALS)||(LA28_192 >= LESSTHAN && LA28_192 <= LESSTHANOREQUALS)||LA28_192==NOTEQUALS) && ((strict == false))) {s = 16;} + else if ( (LA28_192==EOF||LA28_192==AND||(LA28_192 >= OR && LA28_192 <= ORDER)||LA28_192==RPAREN) ) {s = 132;} + + input.seek(index28_192); + if ( s>=0 ) return s; + break; + + case 27 : + int LA28_207 = input.LA(1); + + int index28_207 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_207==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_207); + if ( s>=0 ) return s; + break; + + case 28 : + int LA28_31 = input.LA(1); + + int index28_31 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_31==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_31); + if ( s>=0 ) return s; + break; + + case 29 : + int LA28_206 = input.LA(1); + + int index28_206 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_206==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_206); + if ( s>=0 ) return s; + break; + + case 30 : + int LA28_205 = input.LA(1); + + int index28_205 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_205==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_205); + if ( s>=0 ) return s; + break; + + case 31 : + int LA28_53 = input.LA(1); + + int index28_53 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_53==ID) ) {s = 64;} + else if ( (LA28_53==DOUBLE_QUOTE) ) {s = 65;} + else if ( (LA28_53==COLON||LA28_53==DECIMAL_INTEGER_LITERAL||(LA28_53 >= FALSE && LA28_53 <= FLOATING_POINT_LITERAL)||LA28_53==RPAREN||(LA28_53 >= TIMESTAMP && LA28_53 <= TRUE)) && ((strict == false))) {s = 16;} + else if ( (LA28_53==QUOTED_STRING) ) {s = 66;} + + input.seek(index28_53); + if ( s>=0 ) return s; + break; + + case 32 : + int LA28_52 = input.LA(1); + + int index28_52 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_52==ID) ) {s = 61;} + else if ( (LA28_52==DOUBLE_QUOTE) ) {s = 62;} + else if ( (LA28_52==COLON||LA28_52==DECIMAL_INTEGER_LITERAL||(LA28_52 >= FALSE && LA28_52 <= FLOATING_POINT_LITERAL)||LA28_52==RPAREN||(LA28_52 >= TIMESTAMP && LA28_52 <= TRUE)) && ((strict == false))) {s = 16;} + else if ( (LA28_52==QUOTED_STRING) ) {s = 63;} + + input.seek(index28_52); + if ( s>=0 ) return s; + break; + + case 33 : + int LA28_204 = input.LA(1); + + int index28_204 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_204==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_204); + if ( s>=0 ) return s; + break; + + case 34 : + int LA28_0 = input.LA(1); + + int index28_0 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_0==ID) ) {s = 1;} + else if ( (LA28_0==DOUBLE_QUOTE) && ((strict == false))) {s = 2;} + else if ( (LA28_0==SCORE) ) {s = 3;} + else if ( (LA28_0==AND||(LA28_0 >= AS && LA28_0 <= ASC)||LA28_0==BY||LA28_0==DESC||LA28_0==FROM||(LA28_0 >= IN && LA28_0 <= INNER)||(LA28_0 >= IS && LA28_0 <= LEFT)||LA28_0==LIKE||LA28_0==NOT||LA28_0==NULL||(LA28_0 >= ON && LA28_0 <= OUTER)||LA28_0==SELECT||LA28_0==WHERE) && ((strict == false))) {s = 4;} + else if ( (LA28_0==ANY) ) {s = 5;} + else if ( (LA28_0==CONTAINS) ) {s = 6;} + else if ( (LA28_0==IN_FOLDER) ) {s = 7;} + else if ( (LA28_0==IN_TREE) ) {s = 8;} + else if ( (LA28_0==TIMESTAMP) ) {s = 9;} + else if ( (LA28_0==TRUE) ) {s = 10;} + else if ( (LA28_0==FALSE) ) {s = 11;} + else if ( (LA28_0==DECIMAL_INTEGER_LITERAL||LA28_0==FLOATING_POINT_LITERAL||LA28_0==QUOTED_STRING) ) {s = 12;} + else if ( (LA28_0==COLON) && ((strict == false))) {s = 13;} + + input.seek(index28_0); + if ( s>=0 ) return s; + break; + + case 35 : + int LA28_32 = input.LA(1); + + int index28_32 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_32==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_32); + if ( s>=0 ) return s; + break; + + case 36 : + int LA28_203 = input.LA(1); + + int index28_203 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_203==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_203); + if ( s>=0 ) return s; + break; + + case 37 : + int LA28_212 = input.LA(1); + + int index28_212 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_212==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_212); + if ( s>=0 ) return s; + break; + + case 38 : + int LA28_213 = input.LA(1); + + int index28_213 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_213==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_213); + if ( s>=0 ) return s; + break; + + case 39 : + int LA28_47 = input.LA(1); + + int index28_47 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_47==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_47); + if ( s>=0 ) return s; + break; + + case 40 : + int LA28_29 = input.LA(1); + + int index28_29 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_29==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_29); + if ( s>=0 ) return s; + break; + + case 41 : + int LA28_9 = input.LA(1); + + int index28_9 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_9==QUOTED_STRING) ) {s = 54;} + else if ( (LA28_9==LPAREN) && ((strict == false))) {s = 16;} + + input.seek(index28_9); + if ( s>=0 ) return s; + break; + + case 42 : + int LA28_214 = input.LA(1); + + int index28_214 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_214==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_214); + if ( s>=0 ) return s; + break; + + case 43 : + int LA28_194 = input.LA(1); + + int index28_194 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_194==EQUALS||(LA28_194 >= GREATERTHAN && LA28_194 <= GREATERTHANOREQUALS)||(LA28_194 >= LESSTHAN && LA28_194 <= LESSTHANOREQUALS)||LA28_194==NOTEQUALS) && ((strict == false))) {s = 16;} + else if ( (LA28_194==NOT) && ((strict == false))) {s = 97;} + else if ( (LA28_194==IN) && ((strict == false))) {s = 98;} + else if ( (LA28_194==LIKE) && ((strict == false))) {s = 99;} + else if ( (LA28_194==IS) && ((strict == false))) {s = 100;} + + input.seek(index28_194); + if ( s>=0 ) return s; + break; + + case 44 : + int LA28_215 = input.LA(1); + + int index28_215 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_215==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_215); + if ( s>=0 ) return s; + break; + + case 45 : + int LA28_209 = input.LA(1); + + int index28_209 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_209==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_209); + if ( s>=0 ) return s; + break; + + case 46 : + int LA28_30 = input.LA(1); + + int index28_30 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_30==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_30); + if ( s>=0 ) return s; + break; + + case 47 : + int LA28_46 = input.LA(1); + + int index28_46 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_46==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_46); + if ( s>=0 ) return s; + break; + + case 48 : + int LA28_96 = input.LA(1); + + int index28_96 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_96==ID) && ((strict == false))) {s = 194;} + else if ( (LA28_96==DOUBLE_QUOTE) && ((strict == false))) {s = 195;} + + input.seek(index28_96); + if ( s>=0 ) return s; + break; + + case 49 : + int LA28_210 = input.LA(1); + + int index28_210 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_210==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_210); + if ( s>=0 ) return s; + break; + + case 50 : + int LA28_97 = input.LA(1); + + int index28_97 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_97==IN) && ((strict == false))) {s = 98;} + else if ( (LA28_97==LIKE) && ((strict == false))) {s = 99;} + + input.seek(index28_97); + if ( s>=0 ) return s; + break; + + case 51 : + int LA28_211 = input.LA(1); + + int index28_211 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_211==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_211); + if ( s>=0 ) return s; + break; + + case 52 : + int LA28_60 = input.LA(1); + + int index28_60 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_60==RPAREN) ) {s = 131;} + else if ( (LA28_60==COLON||LA28_60==DECIMAL_INTEGER_LITERAL||LA28_60==DOUBLE_QUOTE||(LA28_60 >= FALSE && LA28_60 <= FLOATING_POINT_LITERAL)||LA28_60==ID||LA28_60==QUOTED_STRING||(LA28_60 >= TIMESTAMP && LA28_60 <= TRUE)) && ((strict == false))) {s = 16;} + + input.seek(index28_60); + if ( s>=0 ) return s; + break; + + case 53 : + int LA28_228 = input.LA(1); + + int index28_228 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_228==EQUALS||(LA28_228 >= GREATERTHAN && LA28_228 <= GREATERTHANOREQUALS)||(LA28_228 >= LESSTHAN && LA28_228 <= LESSTHANOREQUALS)||LA28_228==NOTEQUALS) && ((strict == false))) {s = 16;} + else if ( (LA28_228==NOT) && ((strict == false))) {s = 97;} + else if ( (LA28_228==IN) && ((strict == false))) {s = 98;} + else if ( (LA28_228==LIKE) && ((strict == false))) {s = 99;} + else if ( (LA28_228==IS) && ((strict == false))) {s = 100;} + + input.seek(index28_228); + if ( s>=0 ) return s; + break; + + case 54 : + int LA28_219 = input.LA(1); + + int index28_219 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_219==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_219); + if ( s>=0 ) return s; + break; + + case 55 : + int LA28_48 = input.LA(1); + + int index28_48 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_48==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_48); + if ( s>=0 ) return s; + break; + + case 56 : + int LA28_45 = input.LA(1); + + int index28_45 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_45==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_45); + if ( s>=0 ) return s; + break; + + case 57 : + int LA28_220 = input.LA(1); + + int index28_220 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_220==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_220); + if ( s>=0 ) return s; + break; + + case 58 : + int LA28_2 = input.LA(1); + + int index28_2 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_2==SELECT) && ((strict == false))) {s = 21;} + else if ( (LA28_2==AS) && ((strict == false))) {s = 22;} + else if ( (LA28_2==FROM) && ((strict == false))) {s = 23;} + else if ( (LA28_2==JOIN) && ((strict == false))) {s = 24;} + else if ( (LA28_2==INNER) && ((strict == false))) {s = 25;} + else if ( (LA28_2==LEFT) && ((strict == false))) {s = 26;} + else if ( (LA28_2==OUTER) && ((strict == false))) {s = 27;} + else if ( (LA28_2==ON) && ((strict == false))) {s = 28;} + else if ( (LA28_2==WHERE) && ((strict == false))) {s = 29;} + else if ( (LA28_2==OR) && ((strict == false))) {s = 30;} + else if ( (LA28_2==AND) && ((strict == false))) {s = 31;} + else if ( (LA28_2==NOT) && ((strict == false))) {s = 32;} + else if ( (LA28_2==IN) && ((strict == false))) {s = 33;} + else if ( (LA28_2==LIKE) && ((strict == false))) {s = 34;} + else if ( (LA28_2==IS) && ((strict == false))) {s = 35;} + else if ( (LA28_2==NULL) && ((strict == false))) {s = 36;} + else if ( (LA28_2==ANY) && ((strict == false))) {s = 37;} + else if ( (LA28_2==CONTAINS) && ((strict == false))) {s = 38;} + else if ( (LA28_2==IN_FOLDER) && ((strict == false))) {s = 39;} + else if ( (LA28_2==IN_TREE) && ((strict == false))) {s = 40;} + else if ( (LA28_2==ORDER) && ((strict == false))) {s = 41;} + else if ( (LA28_2==BY) && ((strict == false))) {s = 42;} + else if ( (LA28_2==ASC) && ((strict == false))) {s = 43;} + else if ( (LA28_2==DESC) && ((strict == false))) {s = 44;} + else if ( (LA28_2==TIMESTAMP) && ((strict == false))) {s = 45;} + else if ( (LA28_2==TRUE) && ((strict == false))) {s = 46;} + else if ( (LA28_2==FALSE) && ((strict == false))) {s = 47;} + else if ( (LA28_2==SCORE) && ((strict == false))) {s = 48;} + else if ( (LA28_2==ID) && ((strict == false))) {s = 49;} + + input.seek(index28_2); + if ( s>=0 ) return s; + break; + + case 59 : + int LA28_27 = input.LA(1); + + int index28_27 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_27==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_27); + if ( s>=0 ) return s; + break; + + case 60 : + int LA28_221 = input.LA(1); + + int index28_221 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_221==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_221); + if ( s>=0 ) return s; + break; + + case 61 : + int LA28_28 = input.LA(1); + + int index28_28 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_28==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_28); + if ( s>=0 ) return s; + break; + + case 62 : + int LA28_44 = input.LA(1); + + int index28_44 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_44==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_44); + if ( s>=0 ) return s; + break; + + case 63 : + int LA28_216 = input.LA(1); + + int index28_216 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_216==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_216); + if ( s>=0 ) return s; + break; + + case 64 : + int LA28_217 = input.LA(1); + + int index28_217 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_217==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_217); + if ( s>=0 ) return s; + break; + + case 65 : + int LA28_218 = input.LA(1); + + int index28_218 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_218==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_218); + if ( s>=0 ) return s; + break; + + case 66 : + int LA28_1 = input.LA(1); + + int index28_1 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_1==DOT) ) {s = 14;} + else if ( (LA28_1==EQUALS||(LA28_1 >= GREATERTHAN && LA28_1 <= GREATERTHANOREQUALS)||(LA28_1 >= LESSTHAN && LA28_1 <= LESSTHANOREQUALS)||LA28_1==NOTEQUALS) ) {s = 15;} + else if ( (LA28_1==LPAREN) && ((strict == false))) {s = 16;} + else if ( (LA28_1==NOT) ) {s = 17;} + else if ( (LA28_1==IN) ) {s = 18;} + else if ( (LA28_1==LIKE) ) {s = 19;} + else if ( (LA28_1==IS) ) {s = 20;} + + input.seek(index28_1); + if ( s>=0 ) return s; + break; + + case 67 : + int LA28_225 = input.LA(1); + + int index28_225 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_225==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_225); + if ( s>=0 ) return s; + break; + + case 68 : + int LA28_21 = input.LA(1); + + int index28_21 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_21==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_21); + if ( s>=0 ) return s; + break; + + case 69 : + int LA28_43 = input.LA(1); + + int index28_43 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_43==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_43); + if ( s>=0 ) return s; + break; + + case 70 : + int LA28_25 = input.LA(1); + + int index28_25 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_25==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_25); + if ( s>=0 ) return s; + break; + + case 71 : + int LA28_223 = input.LA(1); + + int index28_223 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_223==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_223); + if ( s>=0 ) return s; + break; + + case 72 : + int LA28_222 = input.LA(1); + + int index28_222 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_222==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_222); + if ( s>=0 ) return s; + break; + + case 73 : + int LA28_224 = input.LA(1); + + int index28_224 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_224==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_224); + if ( s>=0 ) return s; + break; + + case 74 : + int LA28_22 = input.LA(1); + + int index28_22 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_22==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_22); + if ( s>=0 ) return s; + break; + + case 75 : + int LA28_26 = input.LA(1); + + int index28_26 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_26==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_26); + if ( s>=0 ) return s; + break; + + case 76 : + int LA28_42 = input.LA(1); + + int index28_42 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_42==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_42); + if ( s>=0 ) return s; + break; + + case 77 : + int LA28_49 = input.LA(1); + + int index28_49 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_49==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_49); + if ( s>=0 ) return s; + break; + + case 78 : + int LA28_226 = input.LA(1); + + int index28_226 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_226==DOUBLE_QUOTE) && ((strict == false))) {s = 228;} + + input.seek(index28_226); + if ( s>=0 ) return s; + break; + + case 79 : + int LA28_23 = input.LA(1); + + int index28_23 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_23==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_23); + if ( s>=0 ) return s; + break; + + case 80 : + int LA28_51 = input.LA(1); + + int index28_51 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_51==ID) ) {s = 58;} + else if ( (LA28_51==DOUBLE_QUOTE) ) {s = 59;} + else if ( (LA28_51==QUOTED_STRING) ) {s = 60;} + else if ( (LA28_51==COLON||LA28_51==DECIMAL_INTEGER_LITERAL||(LA28_51 >= FALSE && LA28_51 <= FLOATING_POINT_LITERAL)||LA28_51==RPAREN||(LA28_51 >= TIMESTAMP && LA28_51 <= TRUE)) && ((strict == false))) {s = 16;} + + input.seek(index28_51); + if ( s>=0 ) return s; + break; + + case 81 : + int LA28_41 = input.LA(1); + + int index28_41 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_41==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_41); + if ( s>=0 ) return s; + break; + + case 82 : + int LA28_131 = input.LA(1); + + int index28_131 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_131==EOF||LA28_131==AND||(LA28_131 >= OR && LA28_131 <= ORDER)||LA28_131==RPAREN) ) {s = 101;} + else if ( (LA28_131==EQUALS||(LA28_131 >= GREATERTHAN && LA28_131 <= GREATERTHANOREQUALS)||(LA28_131 >= LESSTHAN && LA28_131 <= LESSTHANOREQUALS)||LA28_131==NOTEQUALS) && ((strict == false))) {s = 16;} + + input.seek(index28_131); + if ( s>=0 ) return s; + break; + + case 83 : + int LA28_57 = input.LA(1); + + int index28_57 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_57==DOT) && ((strict == false))) {s = 96;} + else if ( (LA28_57==EQUALS||(LA28_57 >= GREATERTHAN && LA28_57 <= GREATERTHANOREQUALS)||(LA28_57 >= LESSTHAN && LA28_57 <= LESSTHANOREQUALS)||LA28_57==NOTEQUALS) && ((strict == false))) {s = 16;} + else if ( (LA28_57==NOT) && ((strict == false))) {s = 97;} + else if ( (LA28_57==IN) && ((strict == false))) {s = 98;} + else if ( (LA28_57==LIKE) && ((strict == false))) {s = 99;} + else if ( (LA28_57==IS) && ((strict == false))) {s = 100;} + + input.seek(index28_57); + if ( s>=0 ) return s; + break; + + case 84 : + int LA28_24 = input.LA(1); + + int index28_24 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_24==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_24); + if ( s>=0 ) return s; + break; + + case 85 : + int LA28_40 = input.LA(1); + + int index28_40 = input.index(); + input.rewind(); + s = -1; + if ( (LA28_40==DOUBLE_QUOTE) && ((strict == false))) {s = 57;} + + input.seek(index28_40); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 28, _s, input); + error(nvae); + throw nvae; + } + } + + static final String DFA34_eotS = + "\151\uffff"; + static final String DFA34_eofS = + "\151\uffff"; + static final String DFA34_minS = + "\1\33\1\30\1\5\1\33\1\65\35\33\1\52\1\5\2\uffff\1\30\36\33\1\65\2\52\1"+ + "\5\2\uffff\35\33\1\52"; + static final String DFA34_maxS = + "\1\45\1\52\1\127\1\45\1\67\35\33\1\52\1\127\2\uffff\1\52\35\33\1\45\1"+ + "\67\2\52\1\127\2\uffff\35\33\1\52"; + static final String DFA34_acceptS = + "\44\uffff\1\1\1\2\43\uffff\1\1\1\2\36\uffff"; + static final String DFA34_specialS = + "\1\46\1\uffff\1\50\2\uffff\1\35\1\26\1\31\1\33\1\44\1\47\1\45\1\37\1\42"+ + "\1\73\1\72\1\75\1\57\1\65\1\63\1\7\1\1\1\20\1\24\1\14\1\32\1\27\1\30\1"+ + "\36\1\34\1\43\1\41\1\52\1\71\4\uffff\1\40\35\uffff\1\16\1\66\1\uffff\1"+ + "\62\1\25\2\uffff\1\12\1\15\1\13\1\21\1\17\1\23\1\22\1\2\1\0\1\4\1\3\1"+ + "\6\1\5\1\11\1\10\1\70\1\67\1\64\1\61\1\60\1\55\1\54\1\51\1\101\1\77\1"+ + "\76\1\74\1\100\1\56\1\53}>"; + static final String[] DFA34_transitionS = { + "\1\2\11\uffff\1\1", + "\1\3\21\uffff\1\4", + "\1\17\1\25\1\6\1\33\1\uffff\1\32\6\uffff\1\26\3\uffff\1\34\11\uffff"+ + "\1\37\1\uffff\1\7\3\uffff\1\41\1\21\1\11\1\27\1\30\1\23\1\10\1\12\2\uffff"+ + "\1\22\5\uffff\1\20\1\uffff\1\24\1\uffff\1\14\1\16\1\31\1\13\15\uffff"+ + "\1\40\1\5\11\uffff\1\35\1\36\1\15", + "\1\43\11\uffff\1\42", + "\1\45\1\uffff\1\44", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\46", + "\1\4", + "\1\61\1\67\1\50\1\75\1\uffff\1\74\6\uffff\1\70\3\uffff\1\76\11\uffff"+ + "\1\101\1\uffff\1\51\3\uffff\1\103\1\63\1\53\1\71\1\72\1\65\1\52\1\54"+ + "\2\uffff\1\64\5\uffff\1\62\1\uffff\1\66\1\uffff\1\56\1\60\1\73\1\55\15"+ + "\uffff\1\102\1\47\11\uffff\1\77\1\100\1\57", + "", + "", + "\1\104\21\uffff\1\105", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\110\11\uffff\1\107", + "\1\112\1\uffff\1\111", + "\1\4", + "\1\105", + "\1\125\1\133\1\114\1\141\1\uffff\1\140\6\uffff\1\134\3\uffff\1\142\11"+ + "\uffff\1\145\1\uffff\1\115\3\uffff\1\147\1\127\1\117\1\135\1\136\1\131"+ + "\1\116\1\120\2\uffff\1\130\5\uffff\1\126\1\uffff\1\132\1\uffff\1\122"+ + "\1\124\1\137\1\121\15\uffff\1\146\1\113\11\uffff\1\143\1\144\1\123", + "", + "", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\150", + "\1\105" + }; + + static final short[] DFA34_eot = DFA.unpackEncodedString(DFA34_eotS); + static final short[] DFA34_eof = DFA.unpackEncodedString(DFA34_eofS); + static final char[] DFA34_min = DFA.unpackEncodedStringToUnsignedChars(DFA34_minS); + static final char[] DFA34_max = DFA.unpackEncodedStringToUnsignedChars(DFA34_maxS); + static final short[] DFA34_accept = DFA.unpackEncodedString(DFA34_acceptS); + static final short[] DFA34_special = DFA.unpackEncodedString(DFA34_specialS); + static final short[][] DFA34_transition; + + static { + int numStates = DFA34_transitionS.length; + DFA34_transition = new short[numStates][]; + for (int i=0; i ^( PRED_EXISTS columnReference NOT ) | columnReference IS NOT NULL -> ^( PRED_EXISTS columnReference ) );"; + } + @Override + public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { + TokenStream input = (TokenStream)_input; + int _s = s; + switch ( s ) { + case 0 : + int LA34_83 = input.LA(1); + + int index34_83 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_83==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_83); + if ( s>=0 ) return s; + break; + + case 1 : + int LA34_21 = input.LA(1); + + int index34_21 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_21==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_21); + if ( s>=0 ) return s; + break; + + case 2 : + int LA34_82 = input.LA(1); + + int index34_82 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_82==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_82); + if ( s>=0 ) return s; + break; + + case 3 : + int LA34_85 = input.LA(1); + + int index34_85 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_85==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_85); + if ( s>=0 ) return s; + break; + + case 4 : + int LA34_84 = input.LA(1); + + int index34_84 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_84==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_84); + if ( s>=0 ) return s; + break; + + case 5 : + int LA34_87 = input.LA(1); + + int index34_87 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_87==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_87); + if ( s>=0 ) return s; + break; + + case 6 : + int LA34_86 = input.LA(1); + + int index34_86 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_86==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_86); + if ( s>=0 ) return s; + break; + + case 7 : + int LA34_20 = input.LA(1); + + int index34_20 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_20==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_20); + if ( s>=0 ) return s; + break; + + case 8 : + int LA34_89 = input.LA(1); + + int index34_89 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_89==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_89); + if ( s>=0 ) return s; + break; + + case 9 : + int LA34_88 = input.LA(1); + + int index34_88 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_88==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_88); + if ( s>=0 ) return s; + break; + + case 10 : + int LA34_75 = input.LA(1); + + int index34_75 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_75==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_75); + if ( s>=0 ) return s; + break; + + case 11 : + int LA34_77 = input.LA(1); + + int index34_77 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_77==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_77); + if ( s>=0 ) return s; + break; + + case 12 : + int LA34_24 = input.LA(1); + + int index34_24 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_24==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_24); + if ( s>=0 ) return s; + break; + + case 13 : + int LA34_76 = input.LA(1); + + int index34_76 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_76==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_76); + if ( s>=0 ) return s; + break; + + case 14 : + int LA34_68 = input.LA(1); + + int index34_68 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_68==ID) && ((strict == false))) {s = 71;} + else if ( (LA34_68==DOUBLE_QUOTE) && ((strict == false))) {s = 72;} + + input.seek(index34_68); + if ( s>=0 ) return s; + break; + + case 15 : + int LA34_79 = input.LA(1); + + int index34_79 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_79==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_79); + if ( s>=0 ) return s; + break; + + case 16 : + int LA34_22 = input.LA(1); + + int index34_22 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_22==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_22); + if ( s>=0 ) return s; + break; + + case 17 : + int LA34_78 = input.LA(1); + + int index34_78 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_78==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_78); + if ( s>=0 ) return s; + break; + + case 18 : + int LA34_81 = input.LA(1); + + int index34_81 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_81==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_81); + if ( s>=0 ) return s; + break; + + case 19 : + int LA34_80 = input.LA(1); + + int index34_80 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_80==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_80); + if ( s>=0 ) return s; + break; + + case 20 : + int LA34_23 = input.LA(1); + + int index34_23 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_23==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_23); + if ( s>=0 ) return s; + break; + + case 21 : + int LA34_72 = input.LA(1); + + int index34_72 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_72==SELECT) && ((strict == false))) {s = 75;} + else if ( (LA34_72==AS) && ((strict == false))) {s = 76;} + else if ( (LA34_72==FROM) && ((strict == false))) {s = 77;} + else if ( (LA34_72==JOIN) && ((strict == false))) {s = 78;} + else if ( (LA34_72==INNER) && ((strict == false))) {s = 79;} + else if ( (LA34_72==LEFT) && ((strict == false))) {s = 80;} + else if ( (LA34_72==OUTER) && ((strict == false))) {s = 81;} + else if ( (LA34_72==ON) && ((strict == false))) {s = 82;} + else if ( (LA34_72==WHERE) && ((strict == false))) {s = 83;} + else if ( (LA34_72==OR) && ((strict == false))) {s = 84;} + else if ( (LA34_72==AND) && ((strict == false))) {s = 85;} + else if ( (LA34_72==NOT) && ((strict == false))) {s = 86;} + else if ( (LA34_72==IN) && ((strict == false))) {s = 87;} + else if ( (LA34_72==LIKE) && ((strict == false))) {s = 88;} + else if ( (LA34_72==IS) && ((strict == false))) {s = 89;} + else if ( (LA34_72==NULL) && ((strict == false))) {s = 90;} + else if ( (LA34_72==ANY) && ((strict == false))) {s = 91;} + else if ( (LA34_72==CONTAINS) && ((strict == false))) {s = 92;} + else if ( (LA34_72==IN_FOLDER) && ((strict == false))) {s = 93;} + else if ( (LA34_72==IN_TREE) && ((strict == false))) {s = 94;} + else if ( (LA34_72==ORDER) && ((strict == false))) {s = 95;} + else if ( (LA34_72==BY) && ((strict == false))) {s = 96;} + else if ( (LA34_72==ASC) && ((strict == false))) {s = 97;} + else if ( (LA34_72==DESC) && ((strict == false))) {s = 98;} + else if ( (LA34_72==TIMESTAMP) && ((strict == false))) {s = 99;} + else if ( (LA34_72==TRUE) && ((strict == false))) {s = 100;} + else if ( (LA34_72==FALSE) && ((strict == false))) {s = 101;} + else if ( (LA34_72==SCORE) && ((strict == false))) {s = 102;} + else if ( (LA34_72==ID) && ((strict == false))) {s = 103;} + + input.seek(index34_72); + if ( s>=0 ) return s; + break; + + case 22 : + int LA34_6 = input.LA(1); + + int index34_6 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_6==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_6); + if ( s>=0 ) return s; + break; + + case 23 : + int LA34_26 = input.LA(1); + + int index34_26 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_26==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_26); + if ( s>=0 ) return s; + break; + + case 24 : + int LA34_27 = input.LA(1); + + int index34_27 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_27==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_27); + if ( s>=0 ) return s; + break; + + case 25 : + int LA34_7 = input.LA(1); + + int index34_7 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_7==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_7); + if ( s>=0 ) return s; + break; + + case 26 : + int LA34_25 = input.LA(1); + + int index34_25 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_25==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_25); + if ( s>=0 ) return s; + break; + + case 27 : + int LA34_8 = input.LA(1); + + int index34_8 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_8==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_8); + if ( s>=0 ) return s; + break; + + case 28 : + int LA34_29 = input.LA(1); + + int index34_29 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_29==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_29); + if ( s>=0 ) return s; + break; + + case 29 : + int LA34_5 = input.LA(1); + + int index34_5 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_5==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_5); + if ( s>=0 ) return s; + break; + + case 30 : + int LA34_28 = input.LA(1); + + int index34_28 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_28==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_28); + if ( s>=0 ) return s; + break; + + case 31 : + int LA34_12 = input.LA(1); + + int index34_12 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_12==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_12); + if ( s>=0 ) return s; + break; + + case 32 : + int LA34_38 = input.LA(1); + + int index34_38 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_38==DOT) && ((strict == false))) {s = 68;} + else if ( (LA34_38==IS) && ((strict == false))) {s = 69;} + + input.seek(index34_38); + if ( s>=0 ) return s; + break; + + case 33 : + int LA34_31 = input.LA(1); + + int index34_31 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_31==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_31); + if ( s>=0 ) return s; + break; + + case 34 : + int LA34_13 = input.LA(1); + + int index34_13 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_13==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_13); + if ( s>=0 ) return s; + break; + + case 35 : + int LA34_30 = input.LA(1); + + int index34_30 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_30==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_30); + if ( s>=0 ) return s; + break; + + case 36 : + int LA34_9 = input.LA(1); + + int index34_9 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_9==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_9); + if ( s>=0 ) return s; + break; + + case 37 : + int LA34_11 = input.LA(1); + + int index34_11 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_11==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_11); + if ( s>=0 ) return s; + break; + + case 38 : + int LA34_0 = input.LA(1); + + int index34_0 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_0==ID) ) {s = 1;} + else if ( (LA34_0==DOUBLE_QUOTE) && ((strict == false))) {s = 2;} + + input.seek(index34_0); + if ( s>=0 ) return s; + break; + + case 39 : + int LA34_10 = input.LA(1); + + int index34_10 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_10==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_10); + if ( s>=0 ) return s; + break; + + case 40 : + int LA34_2 = input.LA(1); + + int index34_2 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_2==SELECT) && ((strict == false))) {s = 5;} + else if ( (LA34_2==AS) && ((strict == false))) {s = 6;} + else if ( (LA34_2==FROM) && ((strict == false))) {s = 7;} + else if ( (LA34_2==JOIN) && ((strict == false))) {s = 8;} + else if ( (LA34_2==INNER) && ((strict == false))) {s = 9;} + else if ( (LA34_2==LEFT) && ((strict == false))) {s = 10;} + else if ( (LA34_2==OUTER) && ((strict == false))) {s = 11;} + else if ( (LA34_2==ON) && ((strict == false))) {s = 12;} + else if ( (LA34_2==WHERE) && ((strict == false))) {s = 13;} + else if ( (LA34_2==OR) && ((strict == false))) {s = 14;} + else if ( (LA34_2==AND) && ((strict == false))) {s = 15;} + else if ( (LA34_2==NOT) && ((strict == false))) {s = 16;} + else if ( (LA34_2==IN) && ((strict == false))) {s = 17;} + else if ( (LA34_2==LIKE) && ((strict == false))) {s = 18;} + else if ( (LA34_2==IS) && ((strict == false))) {s = 19;} + else if ( (LA34_2==NULL) && ((strict == false))) {s = 20;} + else if ( (LA34_2==ANY) && ((strict == false))) {s = 21;} + else if ( (LA34_2==CONTAINS) && ((strict == false))) {s = 22;} + else if ( (LA34_2==IN_FOLDER) && ((strict == false))) {s = 23;} + else if ( (LA34_2==IN_TREE) && ((strict == false))) {s = 24;} + else if ( (LA34_2==ORDER) && ((strict == false))) {s = 25;} + else if ( (LA34_2==BY) && ((strict == false))) {s = 26;} + else if ( (LA34_2==ASC) && ((strict == false))) {s = 27;} + else if ( (LA34_2==DESC) && ((strict == false))) {s = 28;} + else if ( (LA34_2==TIMESTAMP) && ((strict == false))) {s = 29;} + else if ( (LA34_2==TRUE) && ((strict == false))) {s = 30;} + else if ( (LA34_2==FALSE) && ((strict == false))) {s = 31;} + else if ( (LA34_2==SCORE) && ((strict == false))) {s = 32;} + else if ( (LA34_2==ID) && ((strict == false))) {s = 33;} + + input.seek(index34_2); + if ( s>=0 ) return s; + break; + + case 41 : + int LA34_97 = input.LA(1); + + int index34_97 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_97==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_97); + if ( s>=0 ) return s; + break; + + case 42 : + int LA34_32 = input.LA(1); + + int index34_32 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_32==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_32); + if ( s>=0 ) return s; + break; + + case 43 : + int LA34_104 = input.LA(1); + + int index34_104 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_104==IS) && ((strict == false))) {s = 69;} + + input.seek(index34_104); + if ( s>=0 ) return s; + break; + + case 44 : + int LA34_96 = input.LA(1); + + int index34_96 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_96==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_96); + if ( s>=0 ) return s; + break; + + case 45 : + int LA34_95 = input.LA(1); + + int index34_95 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_95==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_95); + if ( s>=0 ) return s; + break; + + case 46 : + int LA34_103 = input.LA(1); + + int index34_103 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_103==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_103); + if ( s>=0 ) return s; + break; + + case 47 : + int LA34_17 = input.LA(1); + + int index34_17 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_17==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_17); + if ( s>=0 ) return s; + break; + + case 48 : + int LA34_94 = input.LA(1); + + int index34_94 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_94==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_94); + if ( s>=0 ) return s; + break; + + case 49 : + int LA34_93 = input.LA(1); + + int index34_93 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_93==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_93); + if ( s>=0 ) return s; + break; + + case 50 : + int LA34_71 = input.LA(1); + + int index34_71 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_71==IS) && ((strict == false))) {s = 69;} + + input.seek(index34_71); + if ( s>=0 ) return s; + break; + + case 51 : + int LA34_19 = input.LA(1); + + int index34_19 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_19==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_19); + if ( s>=0 ) return s; + break; + + case 52 : + int LA34_92 = input.LA(1); + + int index34_92 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_92==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_92); + if ( s>=0 ) return s; + break; + + case 53 : + int LA34_18 = input.LA(1); + + int index34_18 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_18==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_18); + if ( s>=0 ) return s; + break; + + case 54 : + int LA34_69 = input.LA(1); + + int index34_69 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_69==NULL) && ((strict == false))) {s = 73;} + else if ( (LA34_69==NOT) && ((strict == false))) {s = 74;} + + input.seek(index34_69); + if ( s>=0 ) return s; + break; + + case 55 : + int LA34_91 = input.LA(1); + + int index34_91 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_91==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_91); + if ( s>=0 ) return s; + break; + + case 56 : + int LA34_90 = input.LA(1); + + int index34_90 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_90==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_90); + if ( s>=0 ) return s; + break; + + case 57 : + int LA34_33 = input.LA(1); + + int index34_33 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_33==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_33); + if ( s>=0 ) return s; + break; + + case 58 : + int LA34_15 = input.LA(1); + + int index34_15 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_15==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_15); + if ( s>=0 ) return s; + break; + + case 59 : + int LA34_14 = input.LA(1); + + int index34_14 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_14==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_14); + if ( s>=0 ) return s; + break; + + case 60 : + int LA34_101 = input.LA(1); + + int index34_101 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_101==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_101); + if ( s>=0 ) return s; + break; + + case 61 : + int LA34_16 = input.LA(1); + + int index34_16 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_16==DOUBLE_QUOTE) && ((strict == false))) {s = 38;} + + input.seek(index34_16); + if ( s>=0 ) return s; + break; + + case 62 : + int LA34_100 = input.LA(1); + + int index34_100 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_100==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_100); + if ( s>=0 ) return s; + break; + + case 63 : + int LA34_99 = input.LA(1); + + int index34_99 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_99==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_99); + if ( s>=0 ) return s; + break; + + case 64 : + int LA34_102 = input.LA(1); + + int index34_102 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_102==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_102); + if ( s>=0 ) return s; + break; + + case 65 : + int LA34_98 = input.LA(1); + + int index34_98 = input.index(); + input.rewind(); + s = -1; + if ( (LA34_98==DOUBLE_QUOTE) && ((strict == false))) {s = 104;} + + input.seek(index34_98); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 34, _s, input); + error(nvae); + throw nvae; + } + } + + static final String DFA41_eotS = + "\153\uffff"; + static final String DFA41_eofS = + "\1\uffff\1\4\41\uffff\1\4\1\uffff\1\104\40\uffff\1\111\1\113\42\uffff"+ + "\1\113"; + static final String DFA41_minS = + "\1\33\1\10\1\5\1\33\2\uffff\35\33\1\10\1\5\1\10\36\33\2\uffff\2\10\1\5"+ + "\4\uffff\35\33\1\10"; + static final String DFA41_maxS = + "\1\45\1\30\1\127\1\45\2\uffff\35\33\1\25\1\127\1\30\35\33\1\45\2\uffff"+ + "\2\25\1\127\4\uffff\35\33\1\25"; + static final String DFA41_acceptS = + "\4\uffff\1\1\1\2\76\uffff\1\1\1\2\3\uffff\1\1\1\2\1\1\1\2\36\uffff"; + static final String DFA41_specialS = + "\1\43\1\uffff\1\52\3\uffff\1\36\1\26\1\32\1\34\1\47\1\51\1\50\1\42\1\45"+ + "\1\72\1\71\1\74\1\60\1\65\1\63\1\7\1\1\1\20\1\24\1\14\1\33\1\27\1\31\1"+ + "\40\1\35\1\46\1\44\1\54\1\70\2\uffff\1\30\35\uffff\1\16\3\uffff\1\37\1"+ + "\25\4\uffff\1\12\1\15\1\13\1\21\1\17\1\23\1\22\1\2\1\0\1\4\1\3\1\6\1\5"+ + "\1\11\1\10\1\67\1\66\1\64\1\62\1\61\1\56\1\55\1\53\1\100\1\76\1\75\1\73"+ + "\1\77\1\57\1\41}>"; + static final String[] DFA41_transitionS = { + "\1\2\11\uffff\1\1", + "\1\5\6\uffff\1\4\5\uffff\1\5\2\uffff\1\3", + "\1\20\1\26\1\7\1\34\1\uffff\1\33\6\uffff\1\27\3\uffff\1\35\11\uffff"+ + "\1\40\1\uffff\1\10\3\uffff\1\42\1\22\1\12\1\30\1\31\1\24\1\11\1\13\2"+ + "\uffff\1\23\5\uffff\1\21\1\uffff\1\25\1\uffff\1\15\1\17\1\32\1\14\15"+ + "\uffff\1\41\1\6\11\uffff\1\36\1\37\1\16", + "\1\44\11\uffff\1\43", + "", + "", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\45", + "\1\5\6\uffff\1\4\5\uffff\1\5", + "\1\60\1\66\1\47\1\74\1\uffff\1\73\6\uffff\1\67\3\uffff\1\75\11\uffff"+ + "\1\100\1\uffff\1\50\3\uffff\1\102\1\62\1\52\1\70\1\71\1\64\1\51\1\53"+ + "\2\uffff\1\63\5\uffff\1\61\1\uffff\1\65\1\uffff\1\55\1\57\1\72\1\54\15"+ + "\uffff\1\101\1\46\11\uffff\1\76\1\77\1\56", + "\1\105\6\uffff\1\104\5\uffff\1\105\2\uffff\1\103", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\106", + "\1\110\11\uffff\1\107", + "", + "", + "\1\5\6\uffff\1\4\5\uffff\1\112", + "\1\105\6\uffff\1\104\5\uffff\1\114", + "\1\127\1\135\1\116\1\143\1\uffff\1\142\6\uffff\1\136\3\uffff\1\144\11"+ + "\uffff\1\147\1\uffff\1\117\3\uffff\1\151\1\131\1\121\1\137\1\140\1\133"+ + "\1\120\1\122\2\uffff\1\132\5\uffff\1\130\1\uffff\1\134\1\uffff\1\124"+ + "\1\126\1\141\1\123\15\uffff\1\150\1\115\11\uffff\1\145\1\146\1\125", + "", + "", + "", + "", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\152", + "\1\105\6\uffff\1\104\5\uffff\1\114" + }; + + static final short[] DFA41_eot = DFA.unpackEncodedString(DFA41_eotS); + static final short[] DFA41_eof = DFA.unpackEncodedString(DFA41_eofS); + static final char[] DFA41_min = DFA.unpackEncodedStringToUnsignedChars(DFA41_minS); + static final char[] DFA41_max = DFA.unpackEncodedStringToUnsignedChars(DFA41_maxS); + static final short[] DFA41_accept = DFA.unpackEncodedString(DFA41_acceptS); + static final short[] DFA41_special = DFA.unpackEncodedString(DFA41_specialS); + static final short[][] DFA41_transition; + + static { + int numStates = DFA41_transitionS.length; + DFA41_transition = new short[numStates][]; + for (int i=0; i ^( SORT_SPECIFICATION columnReference ASC ) | columnReference (by= ASC |by= DESC ) -> ^( SORT_SPECIFICATION columnReference $by) );"; + } + @Override + public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { + TokenStream input = (TokenStream)_input; + int _s = s; + switch ( s ) { + case 0 : + int LA41_85 = input.LA(1); + + int index41_85 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_85==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_85); + if ( s>=0 ) return s; + break; + + case 1 : + int LA41_22 = input.LA(1); + + int index41_22 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_22==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_22); + if ( s>=0 ) return s; + break; + + case 2 : + int LA41_84 = input.LA(1); + + int index41_84 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_84==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_84); + if ( s>=0 ) return s; + break; + + case 3 : + int LA41_87 = input.LA(1); + + int index41_87 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_87==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_87); + if ( s>=0 ) return s; + break; + + case 4 : + int LA41_86 = input.LA(1); + + int index41_86 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_86==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_86); + if ( s>=0 ) return s; + break; + + case 5 : + int LA41_89 = input.LA(1); + + int index41_89 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_89==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_89); + if ( s>=0 ) return s; + break; + + case 6 : + int LA41_88 = input.LA(1); + + int index41_88 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_88==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_88); + if ( s>=0 ) return s; + break; + + case 7 : + int LA41_21 = input.LA(1); + + int index41_21 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_21==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_21); + if ( s>=0 ) return s; + break; + + case 8 : + int LA41_91 = input.LA(1); + + int index41_91 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_91==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_91); + if ( s>=0 ) return s; + break; + + case 9 : + int LA41_90 = input.LA(1); + + int index41_90 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_90==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_90); + if ( s>=0 ) return s; + break; + + case 10 : + int LA41_77 = input.LA(1); + + int index41_77 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_77==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_77); + if ( s>=0 ) return s; + break; + + case 11 : + int LA41_79 = input.LA(1); + + int index41_79 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_79==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_79); + if ( s>=0 ) return s; + break; + + case 12 : + int LA41_25 = input.LA(1); + + int index41_25 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_25==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_25); + if ( s>=0 ) return s; + break; + + case 13 : + int LA41_78 = input.LA(1); + + int index41_78 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_78==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_78); + if ( s>=0 ) return s; + break; + + case 14 : + int LA41_67 = input.LA(1); + + int index41_67 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_67==ID) && ((strict == false))) {s = 71;} + else if ( (LA41_67==DOUBLE_QUOTE) && ((strict == false))) {s = 72;} + + input.seek(index41_67); + if ( s>=0 ) return s; + break; + + case 15 : + int LA41_81 = input.LA(1); + + int index41_81 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_81==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_81); + if ( s>=0 ) return s; + break; + + case 16 : + int LA41_23 = input.LA(1); + + int index41_23 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_23==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_23); + if ( s>=0 ) return s; + break; + + case 17 : + int LA41_80 = input.LA(1); + + int index41_80 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_80==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_80); + if ( s>=0 ) return s; + break; + + case 18 : + int LA41_83 = input.LA(1); + + int index41_83 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_83==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_83); + if ( s>=0 ) return s; + break; + + case 19 : + int LA41_82 = input.LA(1); + + int index41_82 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_82==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_82); + if ( s>=0 ) return s; + break; + + case 20 : + int LA41_24 = input.LA(1); + + int index41_24 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_24==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_24); + if ( s>=0 ) return s; + break; + + case 21 : + int LA41_72 = input.LA(1); + + int index41_72 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_72==SELECT) && ((strict == false))) {s = 77;} + else if ( (LA41_72==AS) && ((strict == false))) {s = 78;} + else if ( (LA41_72==FROM) && ((strict == false))) {s = 79;} + else if ( (LA41_72==JOIN) && ((strict == false))) {s = 80;} + else if ( (LA41_72==INNER) && ((strict == false))) {s = 81;} + else if ( (LA41_72==LEFT) && ((strict == false))) {s = 82;} + else if ( (LA41_72==OUTER) && ((strict == false))) {s = 83;} + else if ( (LA41_72==ON) && ((strict == false))) {s = 84;} + else if ( (LA41_72==WHERE) && ((strict == false))) {s = 85;} + else if ( (LA41_72==OR) && ((strict == false))) {s = 86;} + else if ( (LA41_72==AND) && ((strict == false))) {s = 87;} + else if ( (LA41_72==NOT) && ((strict == false))) {s = 88;} + else if ( (LA41_72==IN) && ((strict == false))) {s = 89;} + else if ( (LA41_72==LIKE) && ((strict == false))) {s = 90;} + else if ( (LA41_72==IS) && ((strict == false))) {s = 91;} + else if ( (LA41_72==NULL) && ((strict == false))) {s = 92;} + else if ( (LA41_72==ANY) && ((strict == false))) {s = 93;} + else if ( (LA41_72==CONTAINS) && ((strict == false))) {s = 94;} + else if ( (LA41_72==IN_FOLDER) && ((strict == false))) {s = 95;} + else if ( (LA41_72==IN_TREE) && ((strict == false))) {s = 96;} + else if ( (LA41_72==ORDER) && ((strict == false))) {s = 97;} + else if ( (LA41_72==BY) && ((strict == false))) {s = 98;} + else if ( (LA41_72==ASC) && ((strict == false))) {s = 99;} + else if ( (LA41_72==DESC) && ((strict == false))) {s = 100;} + else if ( (LA41_72==TIMESTAMP) && ((strict == false))) {s = 101;} + else if ( (LA41_72==TRUE) && ((strict == false))) {s = 102;} + else if ( (LA41_72==FALSE) && ((strict == false))) {s = 103;} + else if ( (LA41_72==SCORE) && ((strict == false))) {s = 104;} + else if ( (LA41_72==ID) && ((strict == false))) {s = 105;} + + input.seek(index41_72); + if ( s>=0 ) return s; + break; + + case 22 : + int LA41_7 = input.LA(1); + + int index41_7 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_7==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_7); + if ( s>=0 ) return s; + break; + + case 23 : + int LA41_27 = input.LA(1); + + int index41_27 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_27==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_27); + if ( s>=0 ) return s; + break; + + case 24 : + int LA41_37 = input.LA(1); + + int index41_37 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_37==DOT) && ((strict == false))) {s = 67;} + else if ( (LA41_37==EOF||LA41_37==COMMA) && ((strict == false))) {s = 68;} + else if ( (LA41_37==ASC||LA41_37==DESC) && ((strict == false))) {s = 69;} + + input.seek(index41_37); + if ( s>=0 ) return s; + break; + + case 25 : + int LA41_28 = input.LA(1); + + int index41_28 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_28==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_28); + if ( s>=0 ) return s; + break; + + case 26 : + int LA41_8 = input.LA(1); + + int index41_8 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_8==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_8); + if ( s>=0 ) return s; + break; + + case 27 : + int LA41_26 = input.LA(1); + + int index41_26 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_26==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_26); + if ( s>=0 ) return s; + break; + + case 28 : + int LA41_9 = input.LA(1); + + int index41_9 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_9==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_9); + if ( s>=0 ) return s; + break; + + case 29 : + int LA41_30 = input.LA(1); + + int index41_30 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_30==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_30); + if ( s>=0 ) return s; + break; + + case 30 : + int LA41_6 = input.LA(1); + + int index41_6 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_6==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_6); + if ( s>=0 ) return s; + break; + + case 31 : + int LA41_71 = input.LA(1); + + int index41_71 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_71==COMMA) && ((strict == false))) {s = 68;} + else if ( (LA41_71==EOF) && ((strict == false))) {s = 75;} + else if ( (LA41_71==ASC) && ((strict == false))) {s = 69;} + else if ( (LA41_71==DESC) && ((strict == false))) {s = 76;} + + input.seek(index41_71); + if ( s>=0 ) return s; + break; + + case 32 : + int LA41_29 = input.LA(1); + + int index41_29 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_29==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_29); + if ( s>=0 ) return s; + break; + + case 33 : + int LA41_106 = input.LA(1); + + int index41_106 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_106==COMMA) && ((strict == false))) {s = 68;} + else if ( (LA41_106==EOF) && ((strict == false))) {s = 75;} + else if ( (LA41_106==ASC) && ((strict == false))) {s = 69;} + else if ( (LA41_106==DESC) && ((strict == false))) {s = 76;} + + input.seek(index41_106); + if ( s>=0 ) return s; + break; + + case 34 : + int LA41_13 = input.LA(1); + + int index41_13 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_13==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_13); + if ( s>=0 ) return s; + break; + + case 35 : + int LA41_0 = input.LA(1); + + int index41_0 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_0==ID) ) {s = 1;} + else if ( (LA41_0==DOUBLE_QUOTE) && ((strict == false))) {s = 2;} + + input.seek(index41_0); + if ( s>=0 ) return s; + break; + + case 36 : + int LA41_32 = input.LA(1); + + int index41_32 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_32==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_32); + if ( s>=0 ) return s; + break; + + case 37 : + int LA41_14 = input.LA(1); + + int index41_14 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_14==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_14); + if ( s>=0 ) return s; + break; + + case 38 : + int LA41_31 = input.LA(1); + + int index41_31 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_31==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_31); + if ( s>=0 ) return s; + break; + + case 39 : + int LA41_10 = input.LA(1); + + int index41_10 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_10==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_10); + if ( s>=0 ) return s; + break; + + case 40 : + int LA41_12 = input.LA(1); + + int index41_12 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_12==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_12); + if ( s>=0 ) return s; + break; + + case 41 : + int LA41_11 = input.LA(1); + + int index41_11 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_11==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_11); + if ( s>=0 ) return s; + break; + + case 42 : + int LA41_2 = input.LA(1); + + int index41_2 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_2==SELECT) && ((strict == false))) {s = 6;} + else if ( (LA41_2==AS) && ((strict == false))) {s = 7;} + else if ( (LA41_2==FROM) && ((strict == false))) {s = 8;} + else if ( (LA41_2==JOIN) && ((strict == false))) {s = 9;} + else if ( (LA41_2==INNER) && ((strict == false))) {s = 10;} + else if ( (LA41_2==LEFT) && ((strict == false))) {s = 11;} + else if ( (LA41_2==OUTER) && ((strict == false))) {s = 12;} + else if ( (LA41_2==ON) && ((strict == false))) {s = 13;} + else if ( (LA41_2==WHERE) && ((strict == false))) {s = 14;} + else if ( (LA41_2==OR) && ((strict == false))) {s = 15;} + else if ( (LA41_2==AND) && ((strict == false))) {s = 16;} + else if ( (LA41_2==NOT) && ((strict == false))) {s = 17;} + else if ( (LA41_2==IN) && ((strict == false))) {s = 18;} + else if ( (LA41_2==LIKE) && ((strict == false))) {s = 19;} + else if ( (LA41_2==IS) && ((strict == false))) {s = 20;} + else if ( (LA41_2==NULL) && ((strict == false))) {s = 21;} + else if ( (LA41_2==ANY) && ((strict == false))) {s = 22;} + else if ( (LA41_2==CONTAINS) && ((strict == false))) {s = 23;} + else if ( (LA41_2==IN_FOLDER) && ((strict == false))) {s = 24;} + else if ( (LA41_2==IN_TREE) && ((strict == false))) {s = 25;} + else if ( (LA41_2==ORDER) && ((strict == false))) {s = 26;} + else if ( (LA41_2==BY) && ((strict == false))) {s = 27;} + else if ( (LA41_2==ASC) && ((strict == false))) {s = 28;} + else if ( (LA41_2==DESC) && ((strict == false))) {s = 29;} + else if ( (LA41_2==TIMESTAMP) && ((strict == false))) {s = 30;} + else if ( (LA41_2==TRUE) && ((strict == false))) {s = 31;} + else if ( (LA41_2==FALSE) && ((strict == false))) {s = 32;} + else if ( (LA41_2==SCORE) && ((strict == false))) {s = 33;} + else if ( (LA41_2==ID) && ((strict == false))) {s = 34;} + + input.seek(index41_2); + if ( s>=0 ) return s; + break; + + case 43 : + int LA41_99 = input.LA(1); + + int index41_99 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_99==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_99); + if ( s>=0 ) return s; + break; + + case 44 : + int LA41_33 = input.LA(1); + + int index41_33 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_33==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_33); + if ( s>=0 ) return s; + break; + + case 45 : + int LA41_98 = input.LA(1); + + int index41_98 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_98==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_98); + if ( s>=0 ) return s; + break; + + case 46 : + int LA41_97 = input.LA(1); + + int index41_97 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_97==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_97); + if ( s>=0 ) return s; + break; + + case 47 : + int LA41_105 = input.LA(1); + + int index41_105 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_105==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_105); + if ( s>=0 ) return s; + break; + + case 48 : + int LA41_18 = input.LA(1); + + int index41_18 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_18==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_18); + if ( s>=0 ) return s; + break; + + case 49 : + int LA41_96 = input.LA(1); + + int index41_96 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_96==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_96); + if ( s>=0 ) return s; + break; + + case 50 : + int LA41_95 = input.LA(1); + + int index41_95 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_95==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_95); + if ( s>=0 ) return s; + break; + + case 51 : + int LA41_20 = input.LA(1); + + int index41_20 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_20==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_20); + if ( s>=0 ) return s; + break; + + case 52 : + int LA41_94 = input.LA(1); + + int index41_94 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_94==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_94); + if ( s>=0 ) return s; + break; + + case 53 : + int LA41_19 = input.LA(1); + + int index41_19 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_19==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_19); + if ( s>=0 ) return s; + break; + + case 54 : + int LA41_93 = input.LA(1); + + int index41_93 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_93==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_93); + if ( s>=0 ) return s; + break; + + case 55 : + int LA41_92 = input.LA(1); + + int index41_92 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_92==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_92); + if ( s>=0 ) return s; + break; + + case 56 : + int LA41_34 = input.LA(1); + + int index41_34 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_34==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_34); + if ( s>=0 ) return s; + break; + + case 57 : + int LA41_16 = input.LA(1); + + int index41_16 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_16==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_16); + if ( s>=0 ) return s; + break; + + case 58 : + int LA41_15 = input.LA(1); + + int index41_15 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_15==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_15); + if ( s>=0 ) return s; + break; + + case 59 : + int LA41_103 = input.LA(1); + + int index41_103 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_103==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_103); + if ( s>=0 ) return s; + break; + + case 60 : + int LA41_17 = input.LA(1); + + int index41_17 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_17==DOUBLE_QUOTE) && ((strict == false))) {s = 37;} + + input.seek(index41_17); + if ( s>=0 ) return s; + break; + + case 61 : + int LA41_102 = input.LA(1); + + int index41_102 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_102==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_102); + if ( s>=0 ) return s; + break; + + case 62 : + int LA41_101 = input.LA(1); + + int index41_101 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_101==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_101); + if ( s>=0 ) return s; + break; + + case 63 : + int LA41_104 = input.LA(1); + + int index41_104 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_104==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_104); + if ( s>=0 ) return s; + break; + + case 64 : + int LA41_100 = input.LA(1); + + int index41_100 = input.index(); + input.rewind(); + s = -1; + if ( (LA41_100==DOUBLE_QUOTE) && ((strict == false))) {s = 106;} + + input.seek(index41_100); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 41, _s, input); + error(nvae); + throw nvae; + } + } + + public static final BitSet FOLLOW_SELECT_in_query415 = new BitSet(new long[]{0x1EA09FE2882205E0L,0x0000000000E10C00L}); + public static final BitSet FOLLOW_selectList_in_query417 = new BitSet(new long[]{0x0000000200000000L}); + public static final BitSet FOLLOW_fromClause_in_query419 = new BitSet(new long[]{0x0800000000000000L,0x0000000000800000L}); + public static final BitSet FOLLOW_whereClause_in_query421 = new BitSet(new long[]{0x0800000000000000L}); + public static final BitSet FOLLOW_orderByClause_in_query424 = new BitSet(new long[]{0x0000000000000000L}); + public static final BitSet FOLLOW_EOF_in_query427 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_STAR_in_selectList526 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_selectSubList_in_selectList584 = new BitSet(new long[]{0x0000000000008002L}); + public static final BitSet FOLLOW_COMMA_in_selectList587 = new BitSet(new long[]{0x1EA09FE2882205E0L,0x0000000000E00C00L}); + public static final BitSet FOLLOW_selectSubList_in_selectList589 = new BitSet(new long[]{0x0000000000008002L}); + public static final BitSet FOLLOW_valueExpression_in_selectSubList673 = new BitSet(new long[]{0x0000002008000082L}); + public static final BitSet FOLLOW_AS_in_selectSubList676 = new BitSet(new long[]{0x0000002008000000L}); + public static final BitSet FOLLOW_columnName_in_selectSubList679 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_qualifier_in_selectSubList744 = new BitSet(new long[]{0x0000000004000000L}); + public static final BitSet FOLLOW_DOTSTAR_in_selectSubList746 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_columnReference_in_valueExpression837 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_valueFunction_in_valueExpression869 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_qualifier_in_columnReference933 = new BitSet(new long[]{0x0000000001000000L}); + public static final BitSet FOLLOW_DOT_in_columnReference935 = new BitSet(new long[]{0x0000002008000000L}); + public static final BitSet FOLLOW_columnName_in_columnReference939 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_cmisFunction_in_valueFunction1035 = new BitSet(new long[]{0x0002000000000000L}); + public static final BitSet FOLLOW_LPAREN_in_valueFunction1037 = new BitSet(new long[]{0x0000002188080800L,0x0000000000600300L}); + public static final BitSet FOLLOW_functionArgument_in_valueFunction1039 = new BitSet(new long[]{0x0000002188080800L,0x0000000000600300L}); + public static final BitSet FOLLOW_RPAREN_in_valueFunction1042 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_keyWordOrId_in_valueFunction1115 = new BitSet(new long[]{0x0002000000000000L}); + public static final BitSet FOLLOW_LPAREN_in_valueFunction1117 = new BitSet(new long[]{0x0000002188080800L,0x0000000000600300L}); + public static final BitSet FOLLOW_functionArgument_in_valueFunction1119 = new BitSet(new long[]{0x0000002188080800L,0x0000000000600300L}); + public static final BitSet FOLLOW_RPAREN_in_valueFunction1122 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_qualifier_in_functionArgument1211 = new BitSet(new long[]{0x0000000001000000L}); + public static final BitSet FOLLOW_DOT_in_functionArgument1213 = new BitSet(new long[]{0x0000002008000000L}); + public static final BitSet FOLLOW_columnName_in_functionArgument1215 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_identifier_in_functionArgument1277 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_literalOrParameterName_in_functionArgument1289 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_tableName_in_qualifier1328 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_correlationName_in_qualifier1360 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FROM_in_fromClause1423 = new BitSet(new long[]{0x0002002008000000L}); + public static final BitSet FOLLOW_tableReference_in_fromClause1425 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_singleTable_in_tableReference1488 = new BitSet(new long[]{0x0000188000000002L}); + public static final BitSet FOLLOW_joinedTable_in_tableReference1490 = new BitSet(new long[]{0x0000188000000002L}); + public static final BitSet FOLLOW_simpleTable_in_singleTable1588 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_complexTable_in_singleTable1620 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_tableName_in_simpleTable1711 = new BitSet(new long[]{0x0000002008000082L}); + public static final BitSet FOLLOW_AS_in_simpleTable1714 = new BitSet(new long[]{0x0000002008000000L}); + public static final BitSet FOLLOW_correlationName_in_simpleTable1717 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_joinType_in_joinedTable1813 = new BitSet(new long[]{0x0000080000000000L}); + public static final BitSet FOLLOW_JOIN_in_joinedTable1816 = new BitSet(new long[]{0x0002002008000000L}); + public static final BitSet FOLLOW_tableReference_in_joinedTable1818 = new BitSet(new long[]{0x0200000000000000L}); + public static final BitSet FOLLOW_joinSpecification_in_joinedTable1820 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LPAREN_in_complexTable1929 = new BitSet(new long[]{0x0002002008000000L}); + public static final BitSet FOLLOW_singleTable_in_complexTable1931 = new BitSet(new long[]{0x0000188000000000L}); + public static final BitSet FOLLOW_joinedTable_in_complexTable1933 = new BitSet(new long[]{0x0000188000000000L,0x0000000000000200L}); + public static final BitSet FOLLOW_RPAREN_in_complexTable1936 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LPAREN_in_complexTable1999 = new BitSet(new long[]{0x0002000000000000L}); + public static final BitSet FOLLOW_complexTable_in_complexTable2001 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000200L}); + public static final BitSet FOLLOW_RPAREN_in_complexTable2003 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_INNER_in_joinType2056 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LEFT_in_joinType2088 = new BitSet(new long[]{0x1000000000000002L}); + public static final BitSet FOLLOW_OUTER_in_joinType2090 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ON_in_joinSpecification2154 = new BitSet(new long[]{0x0000002008000000L}); + public static final BitSet FOLLOW_columnReference_in_joinSpecification2158 = new BitSet(new long[]{0x0000000020000000L}); + public static final BitSet FOLLOW_EQUALS_in_joinSpecification2160 = new BitSet(new long[]{0x0000002008000000L}); + public static final BitSet FOLLOW_columnReference_in_joinSpecification2164 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_WHERE_in_whereClause2264 = new BitSet(new long[]{0x1EA29FE3882A0DE0L,0x0000000000E00D00L}); + public static final BitSet FOLLOW_searchOrCondition_in_whereClause2266 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_searchAndCondition_in_searchOrCondition2321 = new BitSet(new long[]{0x0400000000000002L}); + public static final BitSet FOLLOW_OR_in_searchOrCondition2324 = new BitSet(new long[]{0x1EA29FE3882A0DE0L,0x0000000000E00D00L}); + public static final BitSet FOLLOW_searchAndCondition_in_searchOrCondition2326 = new BitSet(new long[]{0x0400000000000002L}); + public static final BitSet FOLLOW_searchNotCondition_in_searchAndCondition2412 = new BitSet(new long[]{0x0000000000000022L}); + public static final BitSet FOLLOW_AND_in_searchAndCondition2415 = new BitSet(new long[]{0x1EA29FE3882A0DE0L,0x0000000000E00D00L}); + public static final BitSet FOLLOW_searchNotCondition_in_searchAndCondition2417 = new BitSet(new long[]{0x0000000000000022L}); + public static final BitSet FOLLOW_NOT_in_searchNotCondition2501 = new BitSet(new long[]{0x1EA29FE3882A0DE0L,0x0000000000E00D00L}); + public static final BitSet FOLLOW_searchTest_in_searchNotCondition2503 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_searchTest_in_searchNotCondition2563 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_predicate_in_searchTest2616 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LPAREN_in_searchTest2648 = new BitSet(new long[]{0x1EA29FE3882A0DE0L,0x0000000000E00D00L}); + public static final BitSet FOLLOW_searchOrCondition_in_searchTest2650 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000200L}); + public static final BitSet FOLLOW_RPAREN_in_searchTest2652 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_comparisonPredicate_in_predicate2705 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_inPredicate_in_predicate2717 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_likePredicate_in_predicate2729 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_nullPredicate_in_predicate2741 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_quantifiedComparisonPredicate_in_predicate2753 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_quantifiedInPredicate_in_predicate2765 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_textSearchPredicate_in_predicate2777 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_folderPredicate_in_predicate2789 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_valueExpression_in_comparisonPredicate2822 = new BitSet(new long[]{0x0040601820000000L}); + public static final BitSet FOLLOW_compOp_in_comparisonPredicate2824 = new BitSet(new long[]{0x0000000180080800L,0x0000000000600100L}); + public static final BitSet FOLLOW_literalOrParameterName_in_comparisonPredicate2826 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_literal_in_literalOrParameterName3006 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_parameterName_in_literalOrParameterName3021 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_signedNumericLiteral_in_literal3054 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_characterStringLiteral_in_literal3066 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_booleanLiteral_in_literal3078 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_datetimeLiteral_in_literal3090 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_columnReference_in_inPredicate3123 = new BitSet(new long[]{0x0020004000000000L}); + public static final BitSet FOLLOW_NOT_in_inPredicate3125 = new BitSet(new long[]{0x0000004000000000L}); + public static final BitSet FOLLOW_IN_in_inPredicate3128 = new BitSet(new long[]{0x0002000000000000L}); + public static final BitSet FOLLOW_LPAREN_in_inPredicate3130 = new BitSet(new long[]{0x0000000180080800L,0x0000000000600100L}); + public static final BitSet FOLLOW_inValueList_in_inPredicate3132 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000200L}); + public static final BitSet FOLLOW_RPAREN_in_inPredicate3134 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_literalOrParameterName_in_inValueList3222 = new BitSet(new long[]{0x0000000000008002L}); + public static final BitSet FOLLOW_COMMA_in_inValueList3225 = new BitSet(new long[]{0x0000000180080800L,0x0000000000600100L}); + public static final BitSet FOLLOW_literalOrParameterName_in_inValueList3227 = new BitSet(new long[]{0x0000000000008002L}); + public static final BitSet FOLLOW_columnReference_in_likePredicate3311 = new BitSet(new long[]{0x0020800000000000L}); + public static final BitSet FOLLOW_NOT_in_likePredicate3313 = new BitSet(new long[]{0x0000800000000000L}); + public static final BitSet FOLLOW_LIKE_in_likePredicate3316 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000100L}); + public static final BitSet FOLLOW_characterStringLiteral_in_likePredicate3318 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_columnReference_in_nullPredicate3404 = new BitSet(new long[]{0x0000040000000000L}); + public static final BitSet FOLLOW_IS_in_nullPredicate3406 = new BitSet(new long[]{0x0080000000000000L}); + public static final BitSet FOLLOW_NULL_in_nullPredicate3408 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_columnReference_in_nullPredicate3470 = new BitSet(new long[]{0x0000040000000000L}); + public static final BitSet FOLLOW_IS_in_nullPredicate3472 = new BitSet(new long[]{0x0020000000000000L}); + public static final BitSet FOLLOW_NOT_in_nullPredicate3474 = new BitSet(new long[]{0x0080000000000000L}); + public static final BitSet FOLLOW_NULL_in_nullPredicate3476 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_literalOrParameterName_in_quantifiedComparisonPredicate3557 = new BitSet(new long[]{0x0040601820000000L}); + public static final BitSet FOLLOW_compOp_in_quantifiedComparisonPredicate3559 = new BitSet(new long[]{0x0000000000000040L}); + public static final BitSet FOLLOW_ANY_in_quantifiedComparisonPredicate3561 = new BitSet(new long[]{0x0000002008000000L}); + public static final BitSet FOLLOW_columnReference_in_quantifiedComparisonPredicate3563 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ANY_in_quantifiedInPredicate3650 = new BitSet(new long[]{0x0000002008000000L}); + public static final BitSet FOLLOW_columnReference_in_quantifiedInPredicate3652 = new BitSet(new long[]{0x0020004000000000L}); + public static final BitSet FOLLOW_NOT_in_quantifiedInPredicate3654 = new BitSet(new long[]{0x0000004000000000L}); + public static final BitSet FOLLOW_IN_in_quantifiedInPredicate3657 = new BitSet(new long[]{0x0002000000000000L}); + public static final BitSet FOLLOW_LPAREN_in_quantifiedInPredicate3659 = new BitSet(new long[]{0x0000000180080800L,0x0000000000600100L}); + public static final BitSet FOLLOW_inValueList_in_quantifiedInPredicate3661 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000200L}); + public static final BitSet FOLLOW_RPAREN_in_quantifiedInPredicate3663 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_CONTAINS_in_textSearchPredicate3751 = new BitSet(new long[]{0x0002000000000000L}); + public static final BitSet FOLLOW_LPAREN_in_textSearchPredicate3753 = new BitSet(new long[]{0x0000002008000000L,0x0000000000000100L}); + public static final BitSet FOLLOW_qualifier_in_textSearchPredicate3756 = new BitSet(new long[]{0x0000000000008000L}); + public static final BitSet FOLLOW_COMMA_in_textSearchPredicate3758 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000100L}); + public static final BitSet FOLLOW_textSearchExpression_in_textSearchPredicate3762 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000200L}); + public static final BitSet FOLLOW_RPAREN_in_textSearchPredicate3764 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_IN_FOLDER_in_folderPredicate3848 = new BitSet(new long[]{0x0002000000000000L}); + public static final BitSet FOLLOW_folderPredicateArgs_in_folderPredicate3850 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_IN_TREE_in_folderPredicate3910 = new BitSet(new long[]{0x0002000000000000L}); + public static final BitSet FOLLOW_folderPredicateArgs_in_folderPredicate3912 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LPAREN_in_folderPredicateArgs3993 = new BitSet(new long[]{0x0000002008000000L,0x0000000000000100L}); + public static final BitSet FOLLOW_qualifier_in_folderPredicateArgs3996 = new BitSet(new long[]{0x0000000000008000L}); + public static final BitSet FOLLOW_COMMA_in_folderPredicateArgs3998 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000100L}); + public static final BitSet FOLLOW_folderId_in_folderPredicateArgs4002 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000200L}); + public static final BitSet FOLLOW_RPAREN_in_folderPredicateArgs4004 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ORDER_in_orderByClause4070 = new BitSet(new long[]{0x0000000000000400L}); + public static final BitSet FOLLOW_BY_in_orderByClause4072 = new BitSet(new long[]{0x0000002008000000L}); + public static final BitSet FOLLOW_sortSpecification_in_orderByClause4074 = new BitSet(new long[]{0x0000000000008002L}); + public static final BitSet FOLLOW_COMMA_in_orderByClause4077 = new BitSet(new long[]{0x0000002008000000L}); + public static final BitSet FOLLOW_sortSpecification_in_orderByClause4079 = new BitSet(new long[]{0x0000000000008002L}); + public static final BitSet FOLLOW_columnReference_in_sortSpecification4163 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_columnReference_in_sortSpecification4225 = new BitSet(new long[]{0x0000000000200100L}); + public static final BitSet FOLLOW_ASC_in_sortSpecification4255 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_DESC_in_sortSpecification4277 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_identifier_in_correlationName4371 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_identifier_in_tableName4407 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_identifier_in_columnName4460 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_COLON_in_parameterName4513 = new BitSet(new long[]{0x0000002008000000L}); + public static final BitSet FOLLOW_identifier_in_parameterName4515 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_characterStringLiteral_in_folderId4596 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_QUOTED_STRING_in_textSearchExpression4649 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ID_in_identifier4682 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_DOUBLE_QUOTE_in_identifier4717 = new BitSet(new long[]{0x1EA09FE2802205E0L,0x0000000000E00C00L}); + public static final BitSet FOLLOW_keyWordOrId_in_identifier4719 = new BitSet(new long[]{0x0000000008000000L}); + public static final BitSet FOLLOW_DOUBLE_QUOTE_in_identifier4721 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FLOATING_POINT_LITERAL_in_signedNumericLiteral4800 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_integerLiteral_in_signedNumericLiteral4860 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_DECIMAL_INTEGER_LITERAL_in_integerLiteral4913 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_TRUE_in_booleanLiteral4994 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FALSE_in_booleanLiteral5054 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_TIMESTAMP_in_datetimeLiteral5135 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000100L}); + public static final BitSet FOLLOW_QUOTED_STRING_in_datetimeLiteral5137 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_QUOTED_STRING_in_characterStringLiteral5218 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_SELECT_in_keyWord5299 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_AS_in_keyWord5311 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FROM_in_keyWord5323 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_JOIN_in_keyWord5335 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_INNER_in_keyWord5347 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LEFT_in_keyWord5359 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_OUTER_in_keyWord5371 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ON_in_keyWord5383 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_WHERE_in_keyWord5395 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_OR_in_keyWord5407 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_AND_in_keyWord5419 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_NOT_in_keyWord5431 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_IN_in_keyWord5443 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LIKE_in_keyWord5455 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_IS_in_keyWord5467 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_NULL_in_keyWord5479 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ANY_in_keyWord5491 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_CONTAINS_in_keyWord5503 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_IN_FOLDER_in_keyWord5515 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_IN_TREE_in_keyWord5527 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ORDER_in_keyWord5539 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_BY_in_keyWord5551 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ASC_in_keyWord5563 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_DESC_in_keyWord5575 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_TIMESTAMP_in_keyWord5587 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_TRUE_in_keyWord5599 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FALSE_in_keyWord5611 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_cmisFunction_in_keyWord5623 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_SCORE_in_cmisFunction5656 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_keyWord_in_keyWordOrId5709 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ID_in_keyWordOrId5741 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_tableName_in_synpred1_CMIS1323 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LPAREN_in_synpred2_CMIS1917 = new BitSet(new long[]{0x0002002008000000L}); + public static final BitSet FOLLOW_singleTable_in_synpred2_CMIS1919 = new BitSet(new long[]{0x0000188000000000L}); + public static final BitSet FOLLOW_joinedTable_in_synpred2_CMIS1921 = new BitSet(new long[]{0x0000188000000000L,0x0000000000000200L}); + public static final BitSet FOLLOW_RPAREN_in_synpred2_CMIS1924 = new BitSet(new long[]{0x0000000000000002L}); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTS.g b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTS.g new file mode 100644 index 0000000000..a83635a9d9 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTS.g @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +/* + * Parser for the Alfresco full text query language. + * It may be used stand-alone or embedded, for example, in CMIS SQL contains() + * + */ + +grammar CMIS_FTS; + +options +{ + output = AST; + backtrack = false; +} +/* + * Additional tokens for tree building. + */ + + +tokens +{ + DISJUNCTION; + CONJUNCTION; + TERM; + PHRASE; + DEFAULT; + EXCLUDE; +} +/* + * Make sure the lexer and parser are generated in the correct package + */ + + +@lexer::header +{ +package org.alfresco.repo.search.impl.parsers; +import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; +} + +@header +{ +package org.alfresco.repo.search.impl.parsers; +} +/* + * Embeded java to control the default connective when not specified. + * + * Do not support recover from errors + * + * Add extra detail to teh error message + */ + + +@members +{ + private Stack paraphrases = new Stack(); + + protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException + { + throw new MismatchedTokenException(ttype, input); + } + + public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException + { + throw e; + } + + public String getErrorMessage(RecognitionException e, String[] tokenNames) + { + List stack = getRuleInvocationStack(e, this.getClass().getName()); + String msg = e.getMessage(); + if ( e instanceof UnwantedTokenException ) + { + UnwantedTokenException ute = (UnwantedTokenException)e; + String tokenName=""; + if ( ute.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[ute.expecting]; + } + msg = "extraneous input " + getTokenErrorDisplay(ute.getUnexpectedToken()) + + " expecting "+tokenName; + } + else if ( e instanceof MissingTokenException ) + { + MissingTokenException mte = (MissingTokenException)e; + String tokenName=""; + if ( mte.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mte.expecting]; + } + msg = "missing " + tokenName+" at " + getTokenErrorDisplay(e.token) + + " (" + getLongTokenErrorDisplay(e.token) +")"; + } + else if ( e instanceof MismatchedTokenException ) + { + MismatchedTokenException mte = (MismatchedTokenException)e; + String tokenName=""; + if ( mte.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mte.expecting]; + } + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting " + tokenName +" (" + getLongTokenErrorDisplay(e.token) + ")"; + } + else if ( e instanceof MismatchedTreeNodeException ) + { + MismatchedTreeNodeException mtne = (MismatchedTreeNodeException)e; + String tokenName=""; + if ( mtne.expecting==Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mtne.expecting]; + } + msg = "mismatched tree node: " + mtne.node + " expecting " + tokenName; + } + else if ( e instanceof NoViableAltException ) + { + NoViableAltException nvae = (NoViableAltException)e; + msg = "no viable alternative at input " + getTokenErrorDisplay(e.token) + + "\n\t (decision=" + nvae.decisionNumber + + " state " + nvae.stateNumber + ")" + + " decision=<<" + nvae.grammarDecisionDescription + ">>"; + } + else if ( e instanceof EarlyExitException ) + { + //EarlyExitException eee = (EarlyExitException)e; + // for development, can add "(decision="+eee.decisionNumber+")" + msg = "required (...)+ loop did not match anything at input " + getTokenErrorDisplay(e.token); + } + else if ( e instanceof MismatchedSetException ) + { + MismatchedSetException mse = (MismatchedSetException)e; + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting set " + mse.expecting; + } + else if ( e instanceof MismatchedNotSetException ) + { + MismatchedNotSetException mse = (MismatchedNotSetException)e; + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting set " + mse.expecting; + } + else if ( e instanceof FailedPredicateException ) + { + FailedPredicateException fpe = (FailedPredicateException)e; + msg = "rule " + fpe.ruleName + " failed predicate: {" + fpe.predicateText + "}?"; + } + + if(paraphrases.size() > 0) + { + String paraphrase = (String)paraphrases.peek(); + msg = msg+" "+paraphrase; + } + return msg +"\n\t"+stack; + } + + public String getLongTokenErrorDisplay(Token t) + { + return t.toString(); + } + + + public String getErrorString(RecognitionException e) + { + String hdr = getErrorHeader(e); + String msg = getErrorMessage(e, this.getTokenNames()); + return hdr+" "+msg; + } +} +/* + * Always throw exceptions + */ + + +@rulecatch +{ +catch(RecognitionException e) +{ + throw e; +} +} +/* + * Support for emitting duplicate tokens from the lexer + * - required to emit ranges after matching floating point literals ... + */ + + +@lexer::members +{ +List tokens = new ArrayList(); +public void emit(Token token) { + state.token = token; + tokens.add(token); +} +public Token nextToken() { + nextTokenImpl(); + if ( tokens.size()==0 ) { + return getEOFToken(); + } + return (Token)tokens.remove(0); +} + +public Token nextTokenImpl() { + while (true) + { + state.token = null; + state.channel = Token.DEFAULT_CHANNEL; + state.tokenStartCharIndex = input.index(); + state.tokenStartCharPositionInLine = input.getCharPositionInLine(); + state.tokenStartLine = input.getLine(); + state.text = null; + if ( input.LA(1)==CharStream.EOF ) + { + return getEOFToken(); + } + try + { + mTokens(); + if ( state.token==null ) + { + emit(); + } + else if ( state.token==Token.SKIP_TOKEN ) + { + continue; + } + return state.token; + } + catch (RecognitionException re) + { + throw new CmisInvalidArgumentException(getErrorString(re), re); + } + } + } + + public String getErrorString(RecognitionException e) + { + String hdr = getErrorHeader(e); + String msg = getErrorMessage(e, this.getTokenNames()); + return hdr+" "+msg; + } +} +/* + * Top level query + */ + + +cmisFtsQuery + : + ftsCmisDisjunction EOF + -> ftsCmisDisjunction + ; +/* + * "OR" + * As SQL, OR has lower precedence than implicit AND + */ + + +ftsCmisDisjunction + : + ftsCmisConjunction (or ftsCmisConjunction)* + -> + ^(DISJUNCTION ftsCmisConjunction+) + ; + +ftsCmisConjunction + : + ftsCmisPrefixed+ + -> + ^(CONJUNCTION ftsCmisPrefixed+) + ; + +ftsCmisPrefixed + : + cmisTest + -> + ^(DEFAULT cmisTest) + | MINUS cmisTest + -> + ^(EXCLUDE cmisTest) + ; + +cmisTest + : + cmisTerm + -> + ^(TERM cmisTerm) + | cmisPhrase + -> + ^(PHRASE cmisPhrase) + + ; + +cmisTerm + : + FTSWORD + -> FTSWORD + ; + +cmisPhrase + : + FTSPHRASE + -> FTSPHRASE + ; + +or + : + OR + ; + +// ===== // +// LEXER // +// ===== // + +FTSPHRASE + : + '\'' + ( + F_ESC + | + ~( + '\\' + | '\'' + ) + )* + '\'' + ; + + +fragment +F_ESC + : + '\\' ('\\' | '\'') + ; + +/* + * Simple tokens, note all are case insensitive + */ + + +OR + : + ( + 'O' + | 'o' + ) + ( + 'R' + | 'r' + ) + ; + +MINUS + : + '-' + ; + +/* + * Standard white space + * White space may be escaped by \ in some tokens + */ + + +WS + : + ( + ' ' + | '\t' + | '\r' + | '\n' + )+ + { $channel = HIDDEN; } + ; + + +FTSWORD + : + START_WORD IN_WORD* + ; + +fragment +START_WORD + : + ~ ( + ' ' + | '\t' + | '\r' + | '\n' + | '-' + ) + ; + +fragment +IN_WORD + : + ~ ( + ' ' + | '\t' + | '\r' + | '\n' + ) + ; + diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTS.tokens b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTS.tokens new file mode 100644 index 0000000000..729d283dc5 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTS.tokens @@ -0,0 +1,14 @@ +CONJUNCTION=4 +DEFAULT=5 +DISJUNCTION=6 +EXCLUDE=7 +FTSPHRASE=8 +FTSWORD=9 +F_ESC=10 +IN_WORD=11 +MINUS=12 +OR=13 +PHRASE=14 +START_WORD=15 +TERM=16 +WS=17 diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSLexer.java b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSLexer.java new file mode 100644 index 0000000000..0c1c217872 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSLexer.java @@ -0,0 +1,592 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +// $ANTLR 3.5.2 W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g 2015-06-18 19:37:59 + +package org.alfresco.repo.search.impl.parsers; +import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; + + +import org.antlr.runtime.*; +import java.util.Stack; +import java.util.List; +import java.util.ArrayList; + +@SuppressWarnings("all") +public class CMIS_FTSLexer extends Lexer { + public static final int EOF=-1; + public static final int CONJUNCTION=4; + public static final int DEFAULT=5; + public static final int DISJUNCTION=6; + public static final int EXCLUDE=7; + public static final int FTSPHRASE=8; + public static final int FTSWORD=9; + public static final int F_ESC=10; + public static final int IN_WORD=11; + public static final int MINUS=12; + public static final int OR=13; + public static final int PHRASE=14; + public static final int START_WORD=15; + public static final int TERM=16; + public static final int WS=17; + + List tokens = new ArrayList(); + public void emit(Token token) { + state.token = token; + tokens.add(token); + } + public Token nextToken() { + nextTokenImpl(); + if ( tokens.size()==0 ) { + return getEOFToken(); + } + return (Token)tokens.remove(0); + } + + public Token nextTokenImpl() { + while (true) + { + state.token = null; + state.channel = Token.DEFAULT_CHANNEL; + state.tokenStartCharIndex = input.index(); + state.tokenStartCharPositionInLine = input.getCharPositionInLine(); + state.tokenStartLine = input.getLine(); + state.text = null; + if ( input.LA(1)==CharStream.EOF ) + { + return getEOFToken(); + } + try + { + mTokens(); + if ( state.token==null ) + { + emit(); + } + else if ( state.token==Token.SKIP_TOKEN ) + { + continue; + } + return state.token; + } + catch (RecognitionException re) + { + throw new CmisInvalidArgumentException(getErrorString(re), re); + } + } + } + + public String getErrorString(RecognitionException e) + { + String hdr = getErrorHeader(e); + String msg = getErrorMessage(e, this.getTokenNames()); + return hdr+" "+msg; + } + + + // delegates + // delegators + public Lexer[] getDelegates() { + return new Lexer[] {}; + } + + public CMIS_FTSLexer() {} + public CMIS_FTSLexer(CharStream input) { + this(input, new RecognizerSharedState()); + } + public CMIS_FTSLexer(CharStream input, RecognizerSharedState state) { + super(input,state); + } + @Override public String getGrammarFileName() { return "W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g"; } + + // $ANTLR start "FTSPHRASE" + public final void mFTSPHRASE() throws RecognitionException { + try { + int _type = FTSPHRASE; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:346:9: ( '\\'' ( F_ESC |~ ( '\\\\' | '\\'' ) )* '\\'' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:347:9: '\\'' ( F_ESC |~ ( '\\\\' | '\\'' ) )* '\\'' + { + match('\''); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:348:9: ( F_ESC |~ ( '\\\\' | '\\'' ) )* + loop1: + while (true) { + int alt1=3; + int LA1_0 = input.LA(1); + if ( (LA1_0=='\\') ) { + alt1=1; + } + else if ( ((LA1_0 >= '\u0000' && LA1_0 <= '&')||(LA1_0 >= '(' && LA1_0 <= '[')||(LA1_0 >= ']' && LA1_0 <= '\uFFFF')) ) { + alt1=2; + } + + switch (alt1) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:349:17: F_ESC + { + mF_ESC(); + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:351:17: ~ ( '\\\\' | '\\'' ) + { + if ( (input.LA(1) >= '\u0000' && input.LA(1) <= '&')||(input.LA(1) >= '(' && input.LA(1) <= '[')||(input.LA(1) >= ']' && input.LA(1) <= '\uFFFF') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + break loop1; + } + } + + match('\''); + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "FTSPHRASE" + + // $ANTLR start "F_ESC" + public final void mF_ESC() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:363:9: ( '\\\\' ( '\\\\' | '\\'' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:364:9: '\\\\' ( '\\\\' | '\\'' ) + { + match('\\'); + if ( input.LA(1)=='\''||input.LA(1)=='\\' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "F_ESC" + + // $ANTLR start "OR" + public final void mOR() throws RecognitionException { + try { + int _type = OR; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:372:9: ( ( 'O' | 'o' ) ( 'R' | 'r' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:373:9: ( 'O' | 'o' ) ( 'R' | 'r' ) + { + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "OR" + + // $ANTLR start "MINUS" + public final void mMINUS() throws RecognitionException { + try { + int _type = MINUS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:384:9: ( '-' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:385:9: '-' + { + match('-'); + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "MINUS" + + // $ANTLR start "WS" + public final void mWS() throws RecognitionException { + try { + int _type = WS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:395:9: ( ( ' ' | '\\t' | '\\r' | '\\n' )+ ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:396:9: ( ' ' | '\\t' | '\\r' | '\\n' )+ + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:396:9: ( ' ' | '\\t' | '\\r' | '\\n' )+ + int cnt2=0; + loop2: + while (true) { + int alt2=2; + int LA2_0 = input.LA(1); + if ( ((LA2_0 >= '\t' && LA2_0 <= '\n')||LA2_0=='\r'||LA2_0==' ') ) { + alt2=1; + } + + switch (alt2) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g: + { + if ( (input.LA(1) >= '\t' && input.LA(1) <= '\n')||input.LA(1)=='\r'||input.LA(1)==' ' ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + if ( cnt2 >= 1 ) break loop2; + EarlyExitException eee = new EarlyExitException(2, input); + throw eee; + } + cnt2++; + } + + _channel = HIDDEN; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "WS" + + // $ANTLR start "FTSWORD" + public final void mFTSWORD() throws RecognitionException { + try { + int _type = FTSWORD; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:407:9: ( START_WORD ( IN_WORD )* ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:408:9: START_WORD ( IN_WORD )* + { + mSTART_WORD(); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:408:20: ( IN_WORD )* + loop3: + while (true) { + int alt3=2; + int LA3_0 = input.LA(1); + if ( ((LA3_0 >= '\u0000' && LA3_0 <= '\b')||(LA3_0 >= '\u000B' && LA3_0 <= '\f')||(LA3_0 >= '\u000E' && LA3_0 <= '\u001F')||(LA3_0 >= '!' && LA3_0 <= '\uFFFF')) ) { + alt3=1; + } + + switch (alt3) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g: + { + if ( (input.LA(1) >= '\u0000' && input.LA(1) <= '\b')||(input.LA(1) >= '\u000B' && input.LA(1) <= '\f')||(input.LA(1) >= '\u000E' && input.LA(1) <= '\u001F')||(input.LA(1) >= '!' && input.LA(1) <= '\uFFFF') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + break loop3; + } + } + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "FTSWORD" + + // $ANTLR start "START_WORD" + public final void mSTART_WORD() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:414:9: (~ ( ' ' | '\\t' | '\\r' | '\\n' | '-' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g: + { + if ( (input.LA(1) >= '\u0000' && input.LA(1) <= '\b')||(input.LA(1) >= '\u000B' && input.LA(1) <= '\f')||(input.LA(1) >= '\u000E' && input.LA(1) <= '\u001F')||(input.LA(1) >= '!' && input.LA(1) <= ',')||(input.LA(1) >= '.' && input.LA(1) <= '\uFFFF') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "START_WORD" + + // $ANTLR start "IN_WORD" + public final void mIN_WORD() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:426:9: (~ ( ' ' | '\\t' | '\\r' | '\\n' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g: + { + if ( (input.LA(1) >= '\u0000' && input.LA(1) <= '\b')||(input.LA(1) >= '\u000B' && input.LA(1) <= '\f')||(input.LA(1) >= '\u000E' && input.LA(1) <= '\u001F')||(input.LA(1) >= '!' && input.LA(1) <= '\uFFFF') ) { + input.consume(); + } + else { + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "IN_WORD" + + @Override + public void mTokens() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:1:8: ( FTSPHRASE | OR | MINUS | WS | FTSWORD ) + int alt4=5; + alt4 = dfa4.predict(input); + switch (alt4) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:1:10: FTSPHRASE + { + mFTSPHRASE(); + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:1:20: OR + { + mOR(); + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:1:23: MINUS + { + mMINUS(); + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:1:29: WS + { + mWS(); + + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:1:32: FTSWORD + { + mFTSWORD(); + + } + break; + + } + } + + + protected DFA4 dfa4 = new DFA4(this); + static final String DFA4_eotS = + "\1\uffff\2\5\3\uffff\2\5\1\11\1\uffff\1\14\1\5\1\uffff"; + static final String DFA4_eofS = + "\15\uffff"; + static final String DFA4_minS = + "\2\0\1\122\3\uffff\1\47\2\0\1\uffff\2\0\1\uffff"; + static final String DFA4_maxS = + "\2\uffff\1\162\3\uffff\1\134\2\uffff\1\uffff\2\uffff\1\uffff"; + static final String DFA4_acceptS = + "\3\uffff\1\3\1\4\1\5\3\uffff\1\1\2\uffff\1\2"; + static final String DFA4_specialS = + "\1\0\1\1\5\uffff\1\5\1\3\1\uffff\1\4\1\2\1\uffff}>"; + static final String[] DFA4_transitionS = { + "\11\5\2\4\2\5\1\4\22\5\1\4\6\5\1\1\5\5\1\3\41\5\1\2\37\5\1\2\uff90\5", + "\11\7\2\11\2\7\1\11\22\7\1\11\6\7\1\10\64\7\1\6\uffa3\7", + "\1\12\37\uffff\1\12", + "", + "", + "", + "\1\13\64\uffff\1\13", + "\11\7\2\11\2\7\1\11\22\7\1\11\6\7\1\10\64\7\1\6\uffa3\7", + "\11\5\2\uffff\2\5\1\uffff\22\5\1\uffff\uffdf\5", + "", + "\11\5\2\uffff\2\5\1\uffff\22\5\1\uffff\uffdf\5", + "\11\7\2\11\2\7\1\11\22\7\1\11\6\7\1\10\64\7\1\6\uffa3\7", + "" + }; + + static final short[] DFA4_eot = DFA.unpackEncodedString(DFA4_eotS); + static final short[] DFA4_eof = DFA.unpackEncodedString(DFA4_eofS); + static final char[] DFA4_min = DFA.unpackEncodedStringToUnsignedChars(DFA4_minS); + static final char[] DFA4_max = DFA.unpackEncodedStringToUnsignedChars(DFA4_maxS); + static final short[] DFA4_accept = DFA.unpackEncodedString(DFA4_acceptS); + static final short[] DFA4_special = DFA.unpackEncodedString(DFA4_specialS); + static final short[][] DFA4_transition; + + static { + int numStates = DFA4_transitionS.length; + DFA4_transition = new short[numStates][]; + for (int i=0; i= '\t' && LA4_0 <= '\n')||LA4_0=='\r'||LA4_0==' ') ) {s = 4;} + else if ( ((LA4_0 >= '\u0000' && LA4_0 <= '\b')||(LA4_0 >= '\u000B' && LA4_0 <= '\f')||(LA4_0 >= '\u000E' && LA4_0 <= '\u001F')||(LA4_0 >= '!' && LA4_0 <= '&')||(LA4_0 >= '(' && LA4_0 <= ',')||(LA4_0 >= '.' && LA4_0 <= 'N')||(LA4_0 >= 'P' && LA4_0 <= 'n')||(LA4_0 >= 'p' && LA4_0 <= '\uFFFF')) ) {s = 5;} + if ( s>=0 ) return s; + break; + + case 1 : + int LA4_1 = input.LA(1); + s = -1; + if ( (LA4_1=='\\') ) {s = 6;} + else if ( ((LA4_1 >= '\u0000' && LA4_1 <= '\b')||(LA4_1 >= '\u000B' && LA4_1 <= '\f')||(LA4_1 >= '\u000E' && LA4_1 <= '\u001F')||(LA4_1 >= '!' && LA4_1 <= '&')||(LA4_1 >= '(' && LA4_1 <= '[')||(LA4_1 >= ']' && LA4_1 <= '\uFFFF')) ) {s = 7;} + else if ( (LA4_1=='\'') ) {s = 8;} + else if ( ((LA4_1 >= '\t' && LA4_1 <= '\n')||LA4_1=='\r'||LA4_1==' ') ) {s = 9;} + else s = 5; + if ( s>=0 ) return s; + break; + + case 2 : + int LA4_11 = input.LA(1); + s = -1; + if ( (LA4_11=='\'') ) {s = 8;} + else if ( (LA4_11=='\\') ) {s = 6;} + else if ( ((LA4_11 >= '\u0000' && LA4_11 <= '\b')||(LA4_11 >= '\u000B' && LA4_11 <= '\f')||(LA4_11 >= '\u000E' && LA4_11 <= '\u001F')||(LA4_11 >= '!' && LA4_11 <= '&')||(LA4_11 >= '(' && LA4_11 <= '[')||(LA4_11 >= ']' && LA4_11 <= '\uFFFF')) ) {s = 7;} + else if ( ((LA4_11 >= '\t' && LA4_11 <= '\n')||LA4_11=='\r'||LA4_11==' ') ) {s = 9;} + else s = 5; + if ( s>=0 ) return s; + break; + + case 3 : + int LA4_8 = input.LA(1); + s = -1; + if ( ((LA4_8 >= '\u0000' && LA4_8 <= '\b')||(LA4_8 >= '\u000B' && LA4_8 <= '\f')||(LA4_8 >= '\u000E' && LA4_8 <= '\u001F')||(LA4_8 >= '!' && LA4_8 <= '\uFFFF')) ) {s = 5;} + else s = 9; + if ( s>=0 ) return s; + break; + + case 4 : + int LA4_10 = input.LA(1); + s = -1; + if ( ((LA4_10 >= '\u0000' && LA4_10 <= '\b')||(LA4_10 >= '\u000B' && LA4_10 <= '\f')||(LA4_10 >= '\u000E' && LA4_10 <= '\u001F')||(LA4_10 >= '!' && LA4_10 <= '\uFFFF')) ) {s = 5;} + else s = 12; + if ( s>=0 ) return s; + break; + + case 5 : + int LA4_7 = input.LA(1); + s = -1; + if ( (LA4_7=='\'') ) {s = 8;} + else if ( (LA4_7=='\\') ) {s = 6;} + else if ( ((LA4_7 >= '\u0000' && LA4_7 <= '\b')||(LA4_7 >= '\u000B' && LA4_7 <= '\f')||(LA4_7 >= '\u000E' && LA4_7 <= '\u001F')||(LA4_7 >= '!' && LA4_7 <= '&')||(LA4_7 >= '(' && LA4_7 <= '[')||(LA4_7 >= ']' && LA4_7 <= '\uFFFF')) ) {s = 7;} + else if ( ((LA4_7 >= '\t' && LA4_7 <= '\n')||LA4_7=='\r'||LA4_7==' ') ) {s = 9;} + else s = 5; + if ( s>=0 ) return s; + break; + } + NoViableAltException nvae = + new NoViableAltException(getDescription(), 4, _s, input); + error(nvae); + throw nvae; + } + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSParser.java b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSParser.java new file mode 100644 index 0000000000..534beff0ca --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSParser.java @@ -0,0 +1,994 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +// $ANTLR 3.5.2 W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g 2015-06-18 19:37:58 + +package org.alfresco.repo.search.impl.parsers; + + +import org.antlr.runtime.*; +import java.util.Stack; +import java.util.List; +import java.util.ArrayList; + +import org.antlr.runtime.tree.*; + + +@SuppressWarnings("all") +public class CMIS_FTSParser extends Parser { + public static final String[] tokenNames = new String[] { + "", "", "", "", "CONJUNCTION", "DEFAULT", "DISJUNCTION", + "EXCLUDE", "FTSPHRASE", "FTSWORD", "F_ESC", "IN_WORD", "MINUS", "OR", + "PHRASE", "START_WORD", "TERM", "WS" + }; + public static final int EOF=-1; + public static final int CONJUNCTION=4; + public static final int DEFAULT=5; + public static final int DISJUNCTION=6; + public static final int EXCLUDE=7; + public static final int FTSPHRASE=8; + public static final int FTSWORD=9; + public static final int F_ESC=10; + public static final int IN_WORD=11; + public static final int MINUS=12; + public static final int OR=13; + public static final int PHRASE=14; + public static final int START_WORD=15; + public static final int TERM=16; + public static final int WS=17; + + // delegates + public Parser[] getDelegates() { + return new Parser[] {}; + } + + // delegators + + + public CMIS_FTSParser(TokenStream input) { + this(input, new RecognizerSharedState()); + } + public CMIS_FTSParser(TokenStream input, RecognizerSharedState state) { + super(input, state); + } + + protected TreeAdaptor adaptor = new CommonTreeAdaptor(); + + public void setTreeAdaptor(TreeAdaptor adaptor) { + this.adaptor = adaptor; + } + public TreeAdaptor getTreeAdaptor() { + return adaptor; + } + @Override public String[] getTokenNames() { return CMIS_FTSParser.tokenNames; } + @Override public String getGrammarFileName() { return "W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g"; } + + + private Stack paraphrases = new Stack(); + + protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException + { + throw new MismatchedTokenException(ttype, input); + } + + public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException + { + throw e; + } + + public String getErrorMessage(RecognitionException e, String[] tokenNames) + { + List stack = getRuleInvocationStack(e, this.getClass().getName()); + String msg = e.getMessage(); + if ( e instanceof UnwantedTokenException ) + { + UnwantedTokenException ute = (UnwantedTokenException)e; + String tokenName=""; + if ( ute.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[ute.expecting]; + } + msg = "extraneous input " + getTokenErrorDisplay(ute.getUnexpectedToken()) + + " expecting "+tokenName; + } + else if ( e instanceof MissingTokenException ) + { + MissingTokenException mte = (MissingTokenException)e; + String tokenName=""; + if ( mte.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mte.expecting]; + } + msg = "missing " + tokenName+" at " + getTokenErrorDisplay(e.token) + + " (" + getLongTokenErrorDisplay(e.token) +")"; + } + else if ( e instanceof MismatchedTokenException ) + { + MismatchedTokenException mte = (MismatchedTokenException)e; + String tokenName=""; + if ( mte.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mte.expecting]; + } + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting " + tokenName +" (" + getLongTokenErrorDisplay(e.token) + ")"; + } + else if ( e instanceof MismatchedTreeNodeException ) + { + MismatchedTreeNodeException mtne = (MismatchedTreeNodeException)e; + String tokenName=""; + if ( mtne.expecting==Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mtne.expecting]; + } + msg = "mismatched tree node: " + mtne.node + " expecting " + tokenName; + } + else if ( e instanceof NoViableAltException ) + { + NoViableAltException nvae = (NoViableAltException)e; + msg = "no viable alternative at input " + getTokenErrorDisplay(e.token) + + "\n\t (decision=" + nvae.decisionNumber + + " state " + nvae.stateNumber + ")" + + " decision=<<" + nvae.grammarDecisionDescription + ">>"; + } + else if ( e instanceof EarlyExitException ) + { + //EarlyExitException eee = (EarlyExitException)e; + // for development, can add "(decision="+eee.decisionNumber+")" + msg = "required (...)+ loop did not match anything at input " + getTokenErrorDisplay(e.token); + } + else if ( e instanceof MismatchedSetException ) + { + MismatchedSetException mse = (MismatchedSetException)e; + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting set " + mse.expecting; + } + else if ( e instanceof MismatchedNotSetException ) + { + MismatchedNotSetException mse = (MismatchedNotSetException)e; + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting set " + mse.expecting; + } + else if ( e instanceof FailedPredicateException ) + { + FailedPredicateException fpe = (FailedPredicateException)e; + msg = "rule " + fpe.ruleName + " failed predicate: {" + fpe.predicateText + "}?"; + } + + if(paraphrases.size() > 0) + { + String paraphrase = (String)paraphrases.peek(); + msg = msg+" "+paraphrase; + } + return msg +"\n\t"+stack; + } + + public String getLongTokenErrorDisplay(Token t) + { + return t.toString(); + } + + + public String getErrorString(RecognitionException e) + { + String hdr = getErrorHeader(e); + String msg = getErrorMessage(e, this.getTokenNames()); + return hdr+" "+msg; + } + + + public static class cmisFtsQuery_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "cmisFtsQuery" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:278:1: cmisFtsQuery : ftsCmisDisjunction EOF -> ftsCmisDisjunction ; + public final CMIS_FTSParser.cmisFtsQuery_return cmisFtsQuery() throws RecognitionException { + CMIS_FTSParser.cmisFtsQuery_return retval = new CMIS_FTSParser.cmisFtsQuery_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token EOF2=null; + ParserRuleReturnScope ftsCmisDisjunction1 =null; + + Object EOF2_tree=null; + RewriteRuleTokenStream stream_EOF=new RewriteRuleTokenStream(adaptor,"token EOF"); + RewriteRuleSubtreeStream stream_ftsCmisDisjunction=new RewriteRuleSubtreeStream(adaptor,"rule ftsCmisDisjunction"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:279:9: ( ftsCmisDisjunction EOF -> ftsCmisDisjunction ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:280:9: ftsCmisDisjunction EOF + { + pushFollow(FOLLOW_ftsCmisDisjunction_in_cmisFtsQuery194); + ftsCmisDisjunction1=ftsCmisDisjunction(); + state._fsp--; + + stream_ftsCmisDisjunction.add(ftsCmisDisjunction1.getTree()); + EOF2=(Token)match(input,EOF,FOLLOW_EOF_in_cmisFtsQuery196); + stream_EOF.add(EOF2); + + // AST REWRITE + // elements: ftsCmisDisjunction + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 281:17: -> ftsCmisDisjunction + { + adaptor.addChild(root_0, stream_ftsCmisDisjunction.nextTree()); + } + + + retval.tree = root_0; + + } + + retval.stop = input.LT(-1); + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "cmisFtsQuery" + + + public static class ftsCmisDisjunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsCmisDisjunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:289:1: ftsCmisDisjunction : ftsCmisConjunction ( or ftsCmisConjunction )* -> ^( DISJUNCTION ( ftsCmisConjunction )+ ) ; + public final CMIS_FTSParser.ftsCmisDisjunction_return ftsCmisDisjunction() throws RecognitionException { + CMIS_FTSParser.ftsCmisDisjunction_return retval = new CMIS_FTSParser.ftsCmisDisjunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope ftsCmisConjunction3 =null; + ParserRuleReturnScope or4 =null; + ParserRuleReturnScope ftsCmisConjunction5 =null; + + RewriteRuleSubtreeStream stream_ftsCmisConjunction=new RewriteRuleSubtreeStream(adaptor,"rule ftsCmisConjunction"); + RewriteRuleSubtreeStream stream_or=new RewriteRuleSubtreeStream(adaptor,"rule or"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:290:9: ( ftsCmisConjunction ( or ftsCmisConjunction )* -> ^( DISJUNCTION ( ftsCmisConjunction )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:291:9: ftsCmisConjunction ( or ftsCmisConjunction )* + { + pushFollow(FOLLOW_ftsCmisConjunction_in_ftsCmisDisjunction252); + ftsCmisConjunction3=ftsCmisConjunction(); + state._fsp--; + + stream_ftsCmisConjunction.add(ftsCmisConjunction3.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:291:28: ( or ftsCmisConjunction )* + loop1: + while (true) { + int alt1=2; + int LA1_0 = input.LA(1); + if ( (LA1_0==OR) ) { + alt1=1; + } + + switch (alt1) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:291:29: or ftsCmisConjunction + { + pushFollow(FOLLOW_or_in_ftsCmisDisjunction255); + or4=or(); + state._fsp--; + + stream_or.add(or4.getTree()); + pushFollow(FOLLOW_ftsCmisConjunction_in_ftsCmisDisjunction257); + ftsCmisConjunction5=ftsCmisConjunction(); + state._fsp--; + + stream_ftsCmisConjunction.add(ftsCmisConjunction5.getTree()); + } + break; + + default : + break loop1; + } + } + + // AST REWRITE + // elements: ftsCmisConjunction + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 292:17: -> ^( DISJUNCTION ( ftsCmisConjunction )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:293:25: ^( DISJUNCTION ( ftsCmisConjunction )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(DISJUNCTION, "DISJUNCTION"), root_1); + if ( !(stream_ftsCmisConjunction.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_ftsCmisConjunction.hasNext() ) { + adaptor.addChild(root_1, stream_ftsCmisConjunction.nextTree()); + } + stream_ftsCmisConjunction.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + + } + + retval.stop = input.LT(-1); + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsCmisDisjunction" + + + public static class ftsCmisConjunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsCmisConjunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:296:1: ftsCmisConjunction : ( ftsCmisPrefixed )+ -> ^( CONJUNCTION ( ftsCmisPrefixed )+ ) ; + public final CMIS_FTSParser.ftsCmisConjunction_return ftsCmisConjunction() throws RecognitionException { + CMIS_FTSParser.ftsCmisConjunction_return retval = new CMIS_FTSParser.ftsCmisConjunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope ftsCmisPrefixed6 =null; + + RewriteRuleSubtreeStream stream_ftsCmisPrefixed=new RewriteRuleSubtreeStream(adaptor,"rule ftsCmisPrefixed"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:297:9: ( ( ftsCmisPrefixed )+ -> ^( CONJUNCTION ( ftsCmisPrefixed )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:298:9: ( ftsCmisPrefixed )+ + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:298:9: ( ftsCmisPrefixed )+ + int cnt2=0; + loop2: + while (true) { + int alt2=2; + int LA2_0 = input.LA(1); + if ( ((LA2_0 >= FTSPHRASE && LA2_0 <= FTSWORD)||LA2_0==MINUS) ) { + alt2=1; + } + + switch (alt2) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:298:9: ftsCmisPrefixed + { + pushFollow(FOLLOW_ftsCmisPrefixed_in_ftsCmisConjunction341); + ftsCmisPrefixed6=ftsCmisPrefixed(); + state._fsp--; + + stream_ftsCmisPrefixed.add(ftsCmisPrefixed6.getTree()); + } + break; + + default : + if ( cnt2 >= 1 ) break loop2; + EarlyExitException eee = new EarlyExitException(2, input); + throw eee; + } + cnt2++; + } + + // AST REWRITE + // elements: ftsCmisPrefixed + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 299:17: -> ^( CONJUNCTION ( ftsCmisPrefixed )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:300:25: ^( CONJUNCTION ( ftsCmisPrefixed )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(CONJUNCTION, "CONJUNCTION"), root_1); + if ( !(stream_ftsCmisPrefixed.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_ftsCmisPrefixed.hasNext() ) { + adaptor.addChild(root_1, stream_ftsCmisPrefixed.nextTree()); + } + stream_ftsCmisPrefixed.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + + } + + retval.stop = input.LT(-1); + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsCmisConjunction" + + + public static class ftsCmisPrefixed_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsCmisPrefixed" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:303:1: ftsCmisPrefixed : ( cmisTest -> ^( DEFAULT cmisTest ) | MINUS cmisTest -> ^( EXCLUDE cmisTest ) ); + public final CMIS_FTSParser.ftsCmisPrefixed_return ftsCmisPrefixed() throws RecognitionException { + CMIS_FTSParser.ftsCmisPrefixed_return retval = new CMIS_FTSParser.ftsCmisPrefixed_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token MINUS8=null; + ParserRuleReturnScope cmisTest7 =null; + ParserRuleReturnScope cmisTest9 =null; + + Object MINUS8_tree=null; + RewriteRuleTokenStream stream_MINUS=new RewriteRuleTokenStream(adaptor,"token MINUS"); + RewriteRuleSubtreeStream stream_cmisTest=new RewriteRuleSubtreeStream(adaptor,"rule cmisTest"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:304:9: ( cmisTest -> ^( DEFAULT cmisTest ) | MINUS cmisTest -> ^( EXCLUDE cmisTest ) ) + int alt3=2; + int LA3_0 = input.LA(1); + if ( ((LA3_0 >= FTSPHRASE && LA3_0 <= FTSWORD)) ) { + alt3=1; + } + else if ( (LA3_0==MINUS) ) { + alt3=2; + } + + else { + NoViableAltException nvae = + new NoViableAltException("", 3, 0, input); + throw nvae; + } + + switch (alt3) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:305:9: cmisTest + { + pushFollow(FOLLOW_cmisTest_in_ftsCmisPrefixed424); + cmisTest7=cmisTest(); + state._fsp--; + + stream_cmisTest.add(cmisTest7.getTree()); + // AST REWRITE + // elements: cmisTest + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 306:17: -> ^( DEFAULT cmisTest ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:307:25: ^( DEFAULT cmisTest ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(DEFAULT, "DEFAULT"), root_1); + adaptor.addChild(root_1, stream_cmisTest.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:308:11: MINUS cmisTest + { + MINUS8=(Token)match(input,MINUS,FOLLOW_MINUS_in_ftsCmisPrefixed484); + stream_MINUS.add(MINUS8); + + pushFollow(FOLLOW_cmisTest_in_ftsCmisPrefixed486); + cmisTest9=cmisTest(); + state._fsp--; + + stream_cmisTest.add(cmisTest9.getTree()); + // AST REWRITE + // elements: cmisTest + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 309:17: -> ^( EXCLUDE cmisTest ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:310:25: ^( EXCLUDE cmisTest ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(EXCLUDE, "EXCLUDE"), root_1); + adaptor.addChild(root_1, stream_cmisTest.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + + } + break; + + } + retval.stop = input.LT(-1); + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsCmisPrefixed" + + + public static class cmisTest_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "cmisTest" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:313:1: cmisTest : ( cmisTerm -> ^( TERM cmisTerm ) | cmisPhrase -> ^( PHRASE cmisPhrase ) ); + public final CMIS_FTSParser.cmisTest_return cmisTest() throws RecognitionException { + CMIS_FTSParser.cmisTest_return retval = new CMIS_FTSParser.cmisTest_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope cmisTerm10 =null; + ParserRuleReturnScope cmisPhrase11 =null; + + RewriteRuleSubtreeStream stream_cmisPhrase=new RewriteRuleSubtreeStream(adaptor,"rule cmisPhrase"); + RewriteRuleSubtreeStream stream_cmisTerm=new RewriteRuleSubtreeStream(adaptor,"rule cmisTerm"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:314:9: ( cmisTerm -> ^( TERM cmisTerm ) | cmisPhrase -> ^( PHRASE cmisPhrase ) ) + int alt4=2; + int LA4_0 = input.LA(1); + if ( (LA4_0==FTSWORD) ) { + alt4=1; + } + else if ( (LA4_0==FTSPHRASE) ) { + alt4=2; + } + + else { + NoViableAltException nvae = + new NoViableAltException("", 4, 0, input); + throw nvae; + } + + switch (alt4) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:315:9: cmisTerm + { + pushFollow(FOLLOW_cmisTerm_in_cmisTest567); + cmisTerm10=cmisTerm(); + state._fsp--; + + stream_cmisTerm.add(cmisTerm10.getTree()); + // AST REWRITE + // elements: cmisTerm + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 316:17: -> ^( TERM cmisTerm ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:317:25: ^( TERM cmisTerm ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(TERM, "TERM"), root_1); + adaptor.addChild(root_1, stream_cmisTerm.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:318:11: cmisPhrase + { + pushFollow(FOLLOW_cmisPhrase_in_cmisTest627); + cmisPhrase11=cmisPhrase(); + state._fsp--; + + stream_cmisPhrase.add(cmisPhrase11.getTree()); + // AST REWRITE + // elements: cmisPhrase + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 319:17: -> ^( PHRASE cmisPhrase ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:320:25: ^( PHRASE cmisPhrase ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PHRASE, "PHRASE"), root_1); + adaptor.addChild(root_1, stream_cmisPhrase.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + + } + break; + + } + retval.stop = input.LT(-1); + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "cmisTest" + + + public static class cmisTerm_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "cmisTerm" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:324:1: cmisTerm : FTSWORD -> FTSWORD ; + public final CMIS_FTSParser.cmisTerm_return cmisTerm() throws RecognitionException { + CMIS_FTSParser.cmisTerm_return retval = new CMIS_FTSParser.cmisTerm_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token FTSWORD12=null; + + Object FTSWORD12_tree=null; + RewriteRuleTokenStream stream_FTSWORD=new RewriteRuleTokenStream(adaptor,"token FTSWORD"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:325:9: ( FTSWORD -> FTSWORD ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:326:9: FTSWORD + { + FTSWORD12=(Token)match(input,FTSWORD,FOLLOW_FTSWORD_in_cmisTerm717); + stream_FTSWORD.add(FTSWORD12); + + // AST REWRITE + // elements: FTSWORD + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 327:17: -> FTSWORD + { + adaptor.addChild(root_0, stream_FTSWORD.nextNode()); + } + + + retval.tree = root_0; + + } + + retval.stop = input.LT(-1); + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "cmisTerm" + + + public static class cmisPhrase_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "cmisPhrase" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:330:1: cmisPhrase : FTSPHRASE -> FTSPHRASE ; + public final CMIS_FTSParser.cmisPhrase_return cmisPhrase() throws RecognitionException { + CMIS_FTSParser.cmisPhrase_return retval = new CMIS_FTSParser.cmisPhrase_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token FTSPHRASE13=null; + + Object FTSPHRASE13_tree=null; + RewriteRuleTokenStream stream_FTSPHRASE=new RewriteRuleTokenStream(adaptor,"token FTSPHRASE"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:331:9: ( FTSPHRASE -> FTSPHRASE ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:332:9: FTSPHRASE + { + FTSPHRASE13=(Token)match(input,FTSPHRASE,FOLLOW_FTSPHRASE_in_cmisPhrase770); + stream_FTSPHRASE.add(FTSPHRASE13); + + // AST REWRITE + // elements: FTSPHRASE + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 333:17: -> FTSPHRASE + { + adaptor.addChild(root_0, stream_FTSPHRASE.nextNode()); + } + + + retval.tree = root_0; + + } + + retval.stop = input.LT(-1); + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "cmisPhrase" + + + public static class or_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "or" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:336:1: or : OR ; + public final CMIS_FTSParser.or_return or() throws RecognitionException { + CMIS_FTSParser.or_return retval = new CMIS_FTSParser.or_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token OR14=null; + + Object OR14_tree=null; + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:337:9: ( OR ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS_FTS.g:338:9: OR + { + root_0 = (Object)adaptor.nil(); + + + OR14=(Token)match(input,OR,FOLLOW_OR_in_or823); + OR14_tree = (Object)adaptor.create(OR14); + adaptor.addChild(root_0, OR14_tree); + + } + + retval.stop = input.LT(-1); + + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "or" + + // Delegated rules + + + + public static final BitSet FOLLOW_ftsCmisDisjunction_in_cmisFtsQuery194 = new BitSet(new long[]{0x0000000000000000L}); + public static final BitSet FOLLOW_EOF_in_cmisFtsQuery196 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsCmisConjunction_in_ftsCmisDisjunction252 = new BitSet(new long[]{0x0000000000002002L}); + public static final BitSet FOLLOW_or_in_ftsCmisDisjunction255 = new BitSet(new long[]{0x0000000000001300L}); + public static final BitSet FOLLOW_ftsCmisConjunction_in_ftsCmisDisjunction257 = new BitSet(new long[]{0x0000000000002002L}); + public static final BitSet FOLLOW_ftsCmisPrefixed_in_ftsCmisConjunction341 = new BitSet(new long[]{0x0000000000001302L}); + public static final BitSet FOLLOW_cmisTest_in_ftsCmisPrefixed424 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_MINUS_in_ftsCmisPrefixed484 = new BitSet(new long[]{0x0000000000000300L}); + public static final BitSet FOLLOW_cmisTest_in_ftsCmisPrefixed486 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_cmisTerm_in_cmisTest567 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_cmisPhrase_in_cmisTest627 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSWORD_in_cmisTerm717 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSPHRASE_in_cmisPhrase770 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_OR_in_or823 = new BitSet(new long[]{0x0000000000000002L}); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTS.g b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTS.g new file mode 100644 index 0000000000..a85ee3aaf4 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTS.g @@ -0,0 +1,2418 @@ +/* + * Copyright (C) 2005-2015 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +/* + * Parser for the Alfresco full text query language. + * It may be used stand-alone or embedded, for example, in CMIS SQL contains() + * + */ + +grammar FTS; + +options +{ + output = AST; + backtrack = false; + memoize = false; +} +/* + * Additional tokens for tree building. + */ + + +tokens +{ + FTS; + DISJUNCTION; + CONJUNCTION; + NEGATION; + TERM; + EXACT_TERM; + PHRASE; + EXACT_PHRASE; + SYNONYM; + RANGE; + PROXIMITY; + DEFAULT; + MANDATORY; + OPTIONAL; + EXCLUDE; + FIELD_DISJUNCTION; + FIELD_CONJUNCTION; + FIELD_NEGATION; + FIELD_GROUP; + FIELD_DEFAULT; + FIELD_MANDATORY; + FIELD_OPTIONAL; + FIELD_EXCLUDE; + FG_TERM; + FG_EXACT_TERM; + FG_PHRASE; + FG_EXACT_PHRASE; + FG_SYNONYM; + FG_PROXIMITY; + FG_RANGE; + FIELD_REF; + INCLUSIVE; + EXCLUSIVE; + QUALIFIER; + PREFIX; + NAME_SPACE; + BOOST; + FUZZY; + TEMPLATE; +} +/* + * Make sure the lexer and parser are generated in the correct package + */ + + +@lexer::header +{ +package org.alfresco.repo.search.impl.parsers; +} + +@header +{ +package org.alfresco.repo.search.impl.parsers; +} +/* + * Embeded java to control the default connective when not specified. + * + * Do not support recover from errors + * + * Add extra detail to teh error message + */ + + +@members +{ + public enum Mode + { + CMIS, DEFAULT_CONJUNCTION, DEFAULT_DISJUNCTION + } + + private Stack paraphrases = new Stack(); + + private boolean defaultFieldConjunction = true; + + private Mode mode = Mode.DEFAULT_CONJUNCTION; + + public Mode getMode() + { + return mode; + } + + public void setMode(Mode mode) + { + this.mode = mode; + } + + public boolean defaultFieldConjunction() + { + return defaultFieldConjunction; + } + + public void setDefaultFieldConjunction(boolean defaultFieldConjunction) + { + this.defaultFieldConjunction = defaultFieldConjunction; + } + + protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException + { + throw new MismatchedTokenException(ttype, input); + } + + public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException + { + throw e; + } + + public String getErrorMessage(RecognitionException e, String[] tokenNames) + { + List stack = getRuleInvocationStack(e, this.getClass().getName()); + String msg = e.getMessage(); + if ( e instanceof UnwantedTokenException ) + { + UnwantedTokenException ute = (UnwantedTokenException)e; + String tokenName=""; + if ( ute.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[ute.expecting]; + } + msg = "extraneous input " + getTokenErrorDisplay(ute.getUnexpectedToken()) + + " expecting "+tokenName; + } + else if ( e instanceof MissingTokenException ) + { + MissingTokenException mte = (MissingTokenException)e; + String tokenName=""; + if ( mte.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mte.expecting]; + } + msg = "missing " + tokenName+" at " + getTokenErrorDisplay(e.token) + + " (" + getLongTokenErrorDisplay(e.token) +")"; + } + else if ( e instanceof MismatchedTokenException ) + { + MismatchedTokenException mte = (MismatchedTokenException)e; + String tokenName=""; + if ( mte.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mte.expecting]; + } + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting " + tokenName +" (" + getLongTokenErrorDisplay(e.token) + ")"; + } + else if ( e instanceof MismatchedTreeNodeException ) + { + MismatchedTreeNodeException mtne = (MismatchedTreeNodeException)e; + String tokenName=""; + if ( mtne.expecting==Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mtne.expecting]; + } + msg = "mismatched tree node: " + mtne.node + " expecting " + tokenName; + } + else if ( e instanceof NoViableAltException ) + { + NoViableAltException nvae = (NoViableAltException)e; + msg = "no viable alternative at input " + getTokenErrorDisplay(e.token) + + "\n\t (decision=" + nvae.decisionNumber + + " state " + nvae.stateNumber + ")" + + " decision=<<" + nvae.grammarDecisionDescription + ">>"; + } + else if ( e instanceof EarlyExitException ) + { + //EarlyExitException eee = (EarlyExitException)e; + // for development, can add "(decision="+eee.decisionNumber+")" + msg = "required (...)+ loop did not match anything at input " + getTokenErrorDisplay(e.token); + } + else if ( e instanceof MismatchedSetException ) + { + MismatchedSetException mse = (MismatchedSetException)e; + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting set " + mse.expecting; + } + else if ( e instanceof MismatchedNotSetException ) + { + MismatchedNotSetException mse = (MismatchedNotSetException)e; + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting set " + mse.expecting; + } + else if ( e instanceof FailedPredicateException ) + { + FailedPredicateException fpe = (FailedPredicateException)e; + msg = "rule " + fpe.ruleName + " failed predicate: {" + fpe.predicateText + "}?"; + } + + if(paraphrases.size() > 0) + { + String paraphrase = (String)paraphrases.peek(); + msg = msg+" "+paraphrase; + } + return msg +"\n\t"+stack; + } + + public String getLongTokenErrorDisplay(Token t) + { + return t.toString(); + } + + + public String getErrorString(RecognitionException e) + { + String hdr = getErrorHeader(e); + String msg = getErrorMessage(e, this.getTokenNames()); + return hdr+" "+msg; + } +} +/* + * Always throw exceptions + */ + + +@rulecatch +{ +catch(RecognitionException e) +{ + throw e; +} +} +/* + * Support for emitting duplicate tokens from the lexer + * - required to emit ranges after matching floating point literals ... + */ + + +@lexer::members +{ +List tokens = new ArrayList(); +public void emit(Token token) { + state.token = token; + tokens.add(token); +} +public Token nextToken() { + nextTokenImpl(); + if ( tokens.size()==0 ) { + return getEOFToken(); + } + return (Token)tokens.remove(0); +} + +public Token nextTokenImpl() { + while (true) + { + state.token = null; + state.channel = Token.DEFAULT_CHANNEL; + state.tokenStartCharIndex = input.index(); + state.tokenStartCharPositionInLine = input.getCharPositionInLine(); + state.tokenStartLine = input.getLine(); + state.text = null; + if ( input.LA(1)==CharStream.EOF ) + { + return getEOFToken(); + } + try + { + mTokens(); + if ( state.token==null ) + { + emit(); + } + else if ( state.token==Token.SKIP_TOKEN ) + { + continue; + } + return state.token; + } + catch (RecognitionException re) + { + throw new FTSQueryException(getErrorString(re), re); + } + } + } + + public String getErrorString(RecognitionException e) + { + String hdr = getErrorHeader(e); + String msg = getErrorMessage(e, this.getTokenNames()); + return hdr+" "+msg; + } +} + + +/* + * Top level query + */ + + +ftsQuery + : + ftsDisjunction EOF + -> ftsDisjunction + ; +/* + * "OR" + * As SQL, OR has lower precedence than AND + */ + + +ftsDisjunction + : + {getMode() == Mode.CMIS}? cmisExplicitDisjunction + | {getMode() == Mode.DEFAULT_CONJUNCTION}? ftsExplicitDisjunction + | {getMode() == Mode.DEFAULT_DISJUNCTION}? ftsImplicitDisjunction + ; + +ftsExplicitDisjunction + : + ftsImplicitConjunction (or ftsImplicitConjunction)* + -> + ^(DISJUNCTION ftsImplicitConjunction+) + ; + +cmisExplicitDisjunction + : + cmisConjunction (or cmisConjunction)* + -> + ^(DISJUNCTION cmisConjunction+) + ; + +ftsImplicitDisjunction + : + (or? ftsExplicitConjunction)+ + -> + ^(DISJUNCTION ftsExplicitConjunction+) + ; +/* + * "AND" + */ + + +ftsExplicitConjunction + : + ftsPrefixed (and ftsPrefixed)* + -> + ^(CONJUNCTION ftsPrefixed+) + ; + +ftsImplicitConjunction + : + (and? ftsPrefixed)+ + -> + ^(CONJUNCTION ftsPrefixed+) + ; + +cmisConjunction + : + cmisPrefixed+ + -> + ^(CONJUNCTION cmisPrefixed+) + ; +/* + * Additional info around query compoents + * - negation, default, mandatory, optional, exclude and boost + * These options control how individual elements are embedded in OR and AND + * and how matches affect the overall score. + */ + + +ftsPrefixed + : + (not) => not ftsTest boost? + -> + ^(NEGATION ftsTest boost?) + | ftsTest boost? + -> + ^(DEFAULT ftsTest boost?) + | PLUS ftsTest boost? + -> + ^(MANDATORY ftsTest boost?) + | BAR ftsTest boost? + -> + ^(OPTIONAL ftsTest boost?) + | MINUS ftsTest boost? + -> + ^(EXCLUDE ftsTest boost?) + ; + +cmisPrefixed + : + cmisTest + -> + ^(DEFAULT cmisTest) + | MINUS cmisTest + -> + ^(EXCLUDE cmisTest) + ; +/* + * Individual query components + */ + +ftsTest + : + (ftsFieldGroupProximity) => ftsFieldGroupProximity + -> + ^(PROXIMITY ftsFieldGroupProximity) + | + (ftsRange) => ftsRange + -> + ^(RANGE ftsRange) + | + (ftsFieldGroup) => ftsFieldGroup + -> ftsFieldGroup + | + (ftsTermOrPhrase) => ftsTermOrPhrase + | + (ftsExactTermOrPhrase) => ftsExactTermOrPhrase + | + (ftsTokenisedTermOrPhrase) => ftsTokenisedTermOrPhrase + + + | LPAREN ftsDisjunction RPAREN + -> ftsDisjunction + | template + -> template + ; + +cmisTest + : + cmisTerm + -> + ^(TERM cmisTerm) + | cmisPhrase + -> + ^(PHRASE cmisPhrase) + ; + +template + : + PERCENT tempReference + -> + ^(TEMPLATE tempReference) + | PERCENT LPAREN (tempReference COMMA?)+ RPAREN + -> + ^(TEMPLATE tempReference+) + ; + +fuzzy + : + TILDA number + -> + ^(FUZZY number) + ; + +slop + : + TILDA DECIMAL_INTEGER_LITERAL + -> + ^(FUZZY DECIMAL_INTEGER_LITERAL) + ; + +boost + : + CARAT number + -> + ^(BOOST number) + ; + +ftsTermOrPhrase + : + (fieldReference COLON) => fieldReference COLON + ( + FTSPHRASE ((slop)=> slop)? + -> ^(PHRASE FTSPHRASE fieldReference slop?) + | + ftsWord ((fuzzy) => fuzzy)? + -> ^(TERM ftsWord fieldReference fuzzy?) + ) + | + FTSPHRASE ((slop)=> slop)? + -> ^(PHRASE FTSPHRASE slop?) + | + ftsWord ((fuzzy) => fuzzy)? + -> ^(TERM ftsWord fuzzy?) + ; + + +ftsExactTermOrPhrase + : + EQUALS + ( + (fieldReference COLON) => fieldReference COLON + ( + FTSPHRASE ((slop)=> slop)? + -> ^(EXACT_PHRASE FTSPHRASE fieldReference slop?) + | + ftsWord ((fuzzy) => fuzzy)? + -> ^(EXACT_TERM ftsWord fieldReference fuzzy?) + ) + | + FTSPHRASE ((slop)=> slop)? + -> ^(EXACT_PHRASE FTSPHRASE slop?) + | + ftsWord ((fuzzy) => fuzzy)? + -> ^(EXACT_TERM ftsWord fuzzy?) + ) + ; + + +ftsTokenisedTermOrPhrase + : + TILDA + ( + (fieldReference COLON) => fieldReference COLON + ( + FTSPHRASE ((slop)=> slop)? + -> ^(PHRASE FTSPHRASE fieldReference slop?) + | + ftsWord ((fuzzy) => fuzzy)? + -> ^(TERM ftsWord fieldReference fuzzy?) + ) + | + FTSPHRASE ((slop)=> slop)? + -> ^(PHRASE FTSPHRASE slop?) + | + ftsWord ((fuzzy) => fuzzy)? + -> ^(TERM ftsWord fuzzy?) + ) + ; + + +cmisTerm + : + ftsWord + -> ftsWord + ; + + +cmisPhrase + : + FTSPHRASE + -> FTSPHRASE + ; + + +ftsRange + : + (fieldReference COLON)? ftsFieldGroupRange + -> ftsFieldGroupRange fieldReference? + ; + +ftsFieldGroup + : + fieldReference COLON LPAREN ftsFieldGroupDisjunction RPAREN + -> + ^(FIELD_GROUP fieldReference ftsFieldGroupDisjunction) + ; + +ftsFieldGroupDisjunction + : + {defaultFieldConjunction() == true}? ftsFieldGroupExplicitDisjunction + | {defaultFieldConjunction() == false}? ftsFieldGroupImplicitDisjunction + ; + +ftsFieldGroupExplicitDisjunction + : + ftsFieldGroupImplicitConjunction (or ftsFieldGroupImplicitConjunction)* + -> + ^(FIELD_DISJUNCTION ftsFieldGroupImplicitConjunction+) + ; + +ftsFieldGroupImplicitDisjunction + : + (or? ftsFieldGroupExplicitConjunction)+ + -> + ^(FIELD_DISJUNCTION ftsFieldGroupExplicitConjunction+) + ; +/* + * "AND" + */ + + +ftsFieldGroupExplicitConjunction + : + ftsFieldGroupPrefixed (and ftsFieldGroupPrefixed)* + -> + ^(FIELD_CONJUNCTION ftsFieldGroupPrefixed+) + ; + +ftsFieldGroupImplicitConjunction + : + (and? ftsFieldGroupPrefixed)+ + -> + ^(FIELD_CONJUNCTION ftsFieldGroupPrefixed+) + ; + +ftsFieldGroupPrefixed + : + (not) => not ftsFieldGroupTest boost? + -> + ^(FIELD_NEGATION ftsFieldGroupTest boost?) + | ftsFieldGroupTest boost? + -> + ^(FIELD_DEFAULT ftsFieldGroupTest boost?) + | PLUS ftsFieldGroupTest boost? + -> + ^(FIELD_MANDATORY ftsFieldGroupTest boost?) + | BAR ftsFieldGroupTest boost? + -> + ^(FIELD_OPTIONAL ftsFieldGroupTest boost?) + | MINUS ftsFieldGroupTest boost? + -> + ^(FIELD_EXCLUDE ftsFieldGroupTest boost?) + ; + +ftsFieldGroupTest + : + (ftsFieldGroupProximity) => ftsFieldGroupProximity + -> + ^(FG_PROXIMITY ftsFieldGroupProximity) + | (ftsFieldGroupTerm) => ftsFieldGroupTerm ( (fuzzy) => fuzzy)? + -> + ^(FG_TERM ftsFieldGroupTerm fuzzy?) + | (ftsFieldGroupExactTerm) => ftsFieldGroupExactTerm ( (fuzzy) => fuzzy)? + -> + ^(FG_EXACT_TERM ftsFieldGroupExactTerm fuzzy?) + | (ftsFieldGroupPhrase) => ftsFieldGroupPhrase ( (slop) => slop)? + -> + ^(FG_PHRASE ftsFieldGroupPhrase slop?) + | (ftsFieldGroupExactPhrase) => ftsFieldGroupExactPhrase ( (slop) => slop)? + -> + ^(FG_EXACT_PHRASE ftsFieldGroupExactPhrase slop?) + | (ftsFieldGroupTokenisedPhrase) => ftsFieldGroupTokenisedPhrase ( (slop) => slop)? + -> + ^(FG_PHRASE ftsFieldGroupTokenisedPhrase slop?) + | (ftsFieldGroupSynonym) => ftsFieldGroupSynonym ( (fuzzy) => fuzzy)? + -> + ^(FG_SYNONYM ftsFieldGroupSynonym fuzzy?) + | (ftsFieldGroupRange) => ftsFieldGroupRange + -> + ^(FG_RANGE ftsFieldGroupRange) + | LPAREN ftsFieldGroupDisjunction RPAREN + -> ftsFieldGroupDisjunction + ; + +ftsFieldGroupTerm + : + ftsWord + ; + +ftsFieldGroupExactTerm + : + EQUALS ftsFieldGroupTerm + -> ftsFieldGroupTerm + ; + +ftsFieldGroupPhrase + : + FTSPHRASE + ; + +ftsFieldGroupExactPhrase + : + EQUALS ftsFieldGroupExactPhrase + -> ftsFieldGroupExactPhrase + ; + +ftsFieldGroupTokenisedPhrase + : + TILDA ftsFieldGroupExactPhrase + -> ftsFieldGroupExactPhrase + ; + +ftsFieldGroupSynonym + : + TILDA ftsFieldGroupTerm + -> ftsFieldGroupTerm + ; + +ftsFieldGroupProximity + : + ftsFieldGroupProximityTerm ( (proximityGroup) => proximityGroup ftsFieldGroupProximityTerm)+ + -> ftsFieldGroupProximityTerm (proximityGroup ftsFieldGroupProximityTerm)+ + ; + +ftsFieldGroupProximityTerm + : + ID + | FTSWORD + | FTSPRE + | FTSWILD + | NOT + | TO + | DECIMAL_INTEGER_LITERAL + | FLOATING_POINT_LITERAL + | DATETIME + | STAR + | URI identifier + ; + +proximityGroup + : + STAR (LPAREN DECIMAL_INTEGER_LITERAL? RPAREN)? + -> + ^(PROXIMITY DECIMAL_INTEGER_LITERAL?) + ; + +ftsFieldGroupRange + : + ftsRangeWord DOTDOT ftsRangeWord + -> INCLUSIVE ftsRangeWord ftsRangeWord INCLUSIVE + | range_left ftsRangeWord TO ftsRangeWord range_right + -> range_left ftsRangeWord ftsRangeWord range_right + ; + +range_left + : + LSQUARE + -> INCLUSIVE + | LT + -> EXCLUSIVE + ; + +range_right + : + RSQUARE + -> INCLUSIVE + | GT + -> EXCLUSIVE + ; + +/* Need to fix the generated parser for extra COLON check ??*/ + +fieldReference + : + AT? + ( + (prefix) => prefix + | uri + )? + identifier + -> + ^(FIELD_REF identifier prefix? uri?) + ; + +tempReference + : + AT? + ( + prefix + | uri + )? + identifier + -> + ^(FIELD_REF identifier prefix? uri?) + ; + +prefix + : + identifier COLON + -> + ^(PREFIX identifier) + ; + +uri + : + URI + -> + ^(NAME_SPACE URI) + ; + +identifier + : + (ID DOT ID) => + id1=ID DOT id2=ID + -> {new CommonTree(new CommonToken(FTSLexer.ID, $id1.text+$DOT.text+$id2.text))} + | + ID + -> + ID + | + TO + -> TO + | OR + -> OR + | AND + -> AND + | NOT + -> NOT + ; + +ftsWord + : + ((DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase) => + (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase + | (ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase DOT|COMMA ftsWordBase) => + ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase + | ((DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA)) => + (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) + | (ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA)) => + ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) + | ((DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase) => + (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase + | (ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase) => + ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase + | ((DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA)) => + (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) + | (ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA)) => + ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) + | ((DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase) => + (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase + | (ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase) => + ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase + | ((DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA)) => + (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) + | (ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) ) => + ftsWordBase (DOT|COMMA) ftsWordBase (DOT|COMMA) + | ((DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase) => + (DOT|COMMA) ftsWordBase (DOT|COMMA) ftsWordBase + | (ftsWordBase (DOT|COMMA) ftsWordBase) => + ftsWordBase (DOT|COMMA) ftsWordBase + | ((DOT|COMMA) ftsWordBase (DOT|COMMA)) => + (DOT|COMMA) ftsWordBase (DOT|COMMA) + | (ftsWordBase (DOT|COMMA)) => + ftsWordBase (DOT|COMMA) + | (DOT|COMMA) ftsWordBase + | ftsWordBase + ; + + +ftsWordBase + : + ID + | FTSWORD + | FTSPRE + | FTSWILD + | NOT + | TO + | DECIMAL_INTEGER_LITERAL + | FLOATING_POINT_LITERAL + | STAR + | QUESTION_MARK + | DATETIME + | URI identifier + ; + +number + : + DECIMAL_INTEGER_LITERAL + | FLOATING_POINT_LITERAL + ; + +ftsRangeWord + : + ID + | FTSWORD + | FTSPRE + | FTSWILD + | FTSPHRASE + | DECIMAL_INTEGER_LITERAL + | FLOATING_POINT_LITERAL + | DATETIME + | STAR + | URI identifier + ; + +// + +or + : + OR + | BAR BAR + ; + +and + : + AND + | AMP AMP + ; + +not + : + NOT + | EXCLAMATION + ; + +// ===== // +// LEXER // +// ===== // + +FTSPHRASE + : + '"' + ( + F_ESC + | + ~( + '\\' + | '"' + ) + )* + '"' + | '\'' + ( + F_ESC + | + ~( + '\\' + | '\'' + ) + )* + '\'' + ; +/* + * Basic URI pattern based on the regular expression patttern taken from the RFC (it it not full URI parsing) + * Note this means the language can not use {} anywhere else in the syntax + */ + + +URI + : + '{' + ( + ( + F_URI_ALPHA + | F_URI_DIGIT + | F_URI_OTHER + ) + => + ( + F_URI_ALPHA + | F_URI_DIGIT + | F_URI_OTHER + )+ + COLON + )? + ( + ( ('//') => '//') + ( + ( + F_URI_ALPHA + | F_URI_DIGIT + | F_URI_OTHER + | COLON + ) + => + ( + F_URI_ALPHA + | F_URI_DIGIT + | F_URI_OTHER + | COLON + ) + )* + )? + ( + F_URI_ALPHA + | F_URI_DIGIT + | F_URI_OTHER + | COLON + | '/' + )* + ( + '?' + ( + F_URI_ALPHA + | F_URI_DIGIT + | F_URI_OTHER + | COLON + | '/' + | '?' + )* + )? + ( + '#' + ( + F_URI_ALPHA + | F_URI_DIGIT + | F_URI_OTHER + | COLON + | '/' + | '?' + | '#' + )* + )? + '}' + ; + +fragment +F_URI_ALPHA + : + 'A'..'Z' + | 'a'..'z' + ; + +fragment +F_URI_DIGIT + : + '0'..'9' + ; + +fragment +F_URI_ESC + : + '%' F_HEX F_HEX + ; + +fragment +F_URI_OTHER + : + '-' + | '.' + | '_' + | '~' + | '[' + | ']' + | '@' + | '!' + | '$' + | '&' + | '\'' + | '(' + | ')' + | '*' + | '+' + | ',' + | ';' + | '=' + ; + + + + /** + * DATE literal + */ + +DATETIME + : + (SPECIFICDATETIME | NOW) (FS UNIT)? ( (PLUS|MINUS) DIGIT+ UNIT)* + ; + +fragment UNIT + : + (YEAR | MONTH | DAY | HOUR | MINUTE | SECOND | MILLIS) + ; + +fragment SPECIFICDATETIME + : + DIGIT DIGIT DIGIT DIGIT + ( '-' DIGIT DIGIT ( '-' DIGIT DIGIT ( 'T' (DIGIT DIGIT ( ':' DIGIT DIGIT ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | (( '+' | '-') DIGIT DIGIT ( ':' DIGIT DIGIT)? ) )? )? )? )? )? )? )? )? + ; + +fragment NOW + : + ('N'|'n') ('O'|'o') ('W'|'w') + ; + +fragment YEAR + : + ('Y'|'y') ('E'|'e') ('A'|'a') ('R'|'r') ('S'|'s')? + ; + +fragment MONTH + : + ('M'|'m') ('O'|'o') ('N'|'n') ('T'|'t') ('H'|'h') ('S'|'s')? + ; + +fragment DAY + : + ('D'|'d') ('A'|'a') ('Y'|'y') ('S'|'s')? + | ('D'|'d') ('A'|'a') ('T'|'t') ('E'|'e') + ; + +fragment HOUR + : + ('H'|'h') ('O'|'o') ('U'|'u') ('R'|'r') ('S'|'s')? + ; + +fragment MINUTE + : + ('M'|'m') ('I'|'i') ('N'|'n') ('U'|'u') ('T'|'t') ('E'|'e') ('S'|'s')? + ; + +fragment SECOND + : + ('S'|'s') ('E'|'e') ('C'|'c') ('O'|'o') ('N'|'n') ('D'|'d') ('S'|'s')? + ; + +fragment MILLIS + : + ('M'|'m') ('I'|'i') ('L'|'l') ('L'|'l') ('I'|'i') ('S'|'s') ('E'|'e') ('C'|'c') ('O'|'o') ('N'|'n') ('D'|'d') ('S'|'s')? + | ('M'|'m') ('I'|'i') ('L'|'l') ('L'|'l') ('I'|'i') ('S'|'s')? + ; + +fragment FS + : + '/' + ; + +/* + * Simple tokens, note all are case insensitive + */ + + +OR + : + ( + 'O' + | 'o' + ) + ( + 'R' + | 'r' + ) + ; + +AND + : + ( + 'A' + | 'a' + ) + ( + 'N' + | 'n' + ) + ( + 'D' + | 'd' + ) + ; + +NOT + : + ( + 'N' + | 'n' + ) + ( + 'O' + | 'o' + ) + ( + 'T' + | 't' + ) + ; + +TILDA + : + '~' + ; + +LPAREN + : + '(' + ; + +RPAREN + : + ')' + ; + +PLUS + : + '+' + ; + +MINUS + : + '-' + ; + +COLON + : + ':' + ; + +STAR + : + '*' + ; + +// This is handled sa part for FLOATING_POINT_LITERAL to reduce lexer complexity +fragment DOTDOT + : + '..' + ; + +// This is handled sa part for FLOATING_POINT_LITERAL to reduce lexer complexity +fragment DOT + : + '.' + ; + +AMP + : + '&' + ; + +EXCLAMATION + : + '!' + ; + +BAR + : + '|' + ; + +EQUALS + : + '=' + ; + +QUESTION_MARK + : + '?' + ; + +LCURL + : + '{' + ; + +RCURL + : + '}' + ; + +LSQUARE + : + '[' + ; + +RSQUARE + : + ']' + ; + +TO + : + ( + 'T' + | 't' + ) + ( + 'O' + | 'o' + ) + ; + +COMMA + : + ',' + ; + +CARAT + : + '^' + ; + +DOLLAR + : + '$' + ; + +GT + : + '>' + ; + +LT + : + '<' + ; + +AT + : + '@' + ; + +PERCENT + : + '%' + ; + + +/** + * ID + * _x????_ encoding is supported for invalid sql characters but requires nothing here, they are handled in the code + * Also supports \ style escaping for non CMIS SQL + */ +ID + : + ( + ( '0'..'9' ) + ( '0'..'9' | '$' | '#' | F_ESC )* + )? + ( 'a'..'z' | 'A'..'Z' | '_' ) + ( 'a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '$' | '#' | F_ESC )* + ; + + + + +// This is handled sa part for FLOATING_POINT_LITERAL to reduce lexer complexity +fragment DECIMAL_INTEGER_LITERAL + : + ; + +FLOATING_POINT_LITERAL + : + (PLUS|MINUS)? + ( + DIGIT+ + ( + {input.LA(2) != '.'}?=> DOT + ( + DIGIT+ + ( + EXPONENT + {$type = FLOATING_POINT_LITERAL; } + | + {input.LA(2) != '.'}?=> DOT + { + int index = $text.indexOf('.'); + + CommonToken digits1 = new CommonToken(input, DECIMAL_INTEGER_LITERAL, Token.DEFAULT_CHANNEL, $pos, $pos+index-1); + emit(digits1); + + CommonToken dot1 = new CommonToken(input, DOT, Token.DEFAULT_CHANNEL, $pos+index, $pos+index); + emit(dot1); + + CommonToken digits2 = new CommonToken(input, DECIMAL_INTEGER_LITERAL, Token.DEFAULT_CHANNEL, $pos+index+1, $pos + $text.length() -2); + emit(digits2); + + CommonToken dot2 = new CommonToken(input, DOT, Token.DEFAULT_CHANNEL, $pos + $text.length() -1, $pos + $text.length() -1); + emit(dot2); + + } + | + {$type = FLOATING_POINT_LITERAL; } + ) + | + EXPONENT + {$type = FLOATING_POINT_LITERAL; } + | + {$type = FLOATING_POINT_LITERAL; } + ) + | + ( + EXPONENT + {$type = FLOATING_POINT_LITERAL; } + | + {$type = DECIMAL_INTEGER_LITERAL; } + ) + + ) + | + + DOT + ( + DIGIT+ + ( + EXPONENT + {$type = FLOATING_POINT_LITERAL; } + | + {$text.startsWith(".")}? {input.LA(2) != '.'}?=> DOT + + { + + CommonToken dot1 = new CommonToken(input, DOT, Token.DEFAULT_CHANNEL, $pos, $pos); + emit(dot1); + + CommonToken digits = new CommonToken(input, DECIMAL_INTEGER_LITERAL, Token.DEFAULT_CHANNEL, $pos+1, $pos + $text.length() -2); + emit(digits); + + CommonToken dot2 = new CommonToken(input, DOT, Token.DEFAULT_CHANNEL, $pos + $text.length() -1, $pos + $text.length() -1); + emit(dot2); + + } + | + {$type = FLOATING_POINT_LITERAL; } + + ) + | + {input.LA(2) != '.'}?=> '.' + {$type = DOTDOT; } + | + {$type = DOT; } + ) + ) + ; + + + +/* + * Range and floating point have to be conbined to avoid lexer issues. + * This requires multi-token emits and addition supporting java code - see above ... + * + * Special rules for the likes of + * 1.. integer ranges + * 1... float range with the float terminated by . + * If floats are 'full' e.g. 2.4.. then the parse matches the normal float tokem and a DOTDOT token + * Likewise .1...2 does not require any special support + * + * Float and integer are based on the Java language spec. + */ + +/** + * Fragments for decimal + */ +fragment +DECIMAL_NUMERAL + : + ZERO_DIGIT + | NON_ZERO_DIGIT DIGIT* + ; + +fragment +DIGIT + : + ZERO_DIGIT + | NON_ZERO_DIGIT + ; + +fragment +ZERO_DIGIT + : + '0' + ; + +fragment +NON_ZERO_DIGIT + : + '1'..'9' + ; + +fragment +E + : + ( + 'e' + | 'E' + ) + ; + +fragment +EXPONENT + : + E SIGNED_INTEGER + ; + +fragment +SIGNED_INTEGER + : + ( + PLUS + | MINUS + )? + DIGIT+ + ; + + +FTSWORD + : + ( + F_ESC + | START_WORD + ) + ( + F_ESC + | IN_WORD + )* + ; + +FTSPRE + : + ( + F_ESC + | START_WORD + ) + ( + F_ESC + | IN_WORD + )* + STAR + ; + +FTSWILD + : + ( + F_ESC + | START_WORD + | STAR + | QUESTION_MARK + ) + ( + F_ESC + | IN_WORD + | STAR + | QUESTION_MARK + )* + ; + +fragment +F_ESC + : + '\\' + ( + // unicode + 'u' F_HEX F_HEX F_HEX F_HEX + // any single char escaped + | . + ) + ; + +fragment +F_HEX + : + '0'..'9' + | 'a'..'f' + | 'A'..'F' + ; + +fragment +START_WORD + : // Generated from Java Character.isLetterOrDigit() + '\u0024' + | '\u0030'..'\u0039' + | '\u0041'..'\u005a' + | '\u0061'..'\u007a' + | '\u00a2'..'\u00a7' + | '\u00a9'..'\u00aa' + | '\u00ae' + | '\u00b0' + | '\u00b2'..'\u00b3' + | '\u00b5'..'\u00b6' + | '\u00b9'..'\u00ba' + | '\u00bc'..'\u00be' + | '\u00c0'..'\u00d6' + | '\u00d8'..'\u00f6' + | '\u00f8'..'\u0236' + | '\u0250'..'\u02c1' + | '\u02c6'..'\u02d1' + | '\u02e0'..'\u02e4' + | '\u02ee' + | '\u0300'..'\u0357' + | '\u035d'..'\u036f' + | '\u037a'..'\u037a' + | '\u0386' + | '\u0388'..'\u038a' + | '\u038c'..'\u038c' + | '\u038e'..'\u03a1' + | '\u03a3'..'\u03ce' + | '\u03d0'..'\u03f5' + | '\u03f7'..'\u03fb' + | '\u0400'..'\u0486' + | '\u0488'..'\u04ce' + | '\u04d0'..'\u04f5' + | '\u04f8'..'\u04f9' + | '\u0500'..'\u050f' + | '\u0531'..'\u0556' + | '\u0559' + | '\u0561'..'\u0587' + | '\u0591'..'\u05a1' + | '\u05a3'..'\u05b9' + | '\u05bb'..'\u05bd' + | '\u05bf' + | '\u05c1'..'\u05c2' + | '\u05c4'..'\u05c4' + | '\u05d0'..'\u05ea' + | '\u05f0'..'\u05f2' + | '\u060e'..'\u0615' + | '\u0621'..'\u063a' + | '\u0640'..'\u0658' + | '\u0660'..'\u0669' + | '\u066e'..'\u06d3' + | '\u06d5'..'\u06dc' + | '\u06de'..'\u06ff' + | '\u0710'..'\u074a' + | '\u074d'..'\u074f' + | '\u0780'..'\u07b1' + | '\u0901'..'\u0939' + | '\u093c'..'\u094d' + | '\u0950'..'\u0954' + | '\u0958'..'\u0963' + | '\u0966'..'\u096f' + | '\u0981'..'\u0983' + | '\u0985'..'\u098c' + | '\u098f'..'\u0990' + | '\u0993'..'\u09a8' + | '\u09aa'..'\u09b0' + | '\u09b2'..'\u09b2' + | '\u09b6'..'\u09b9' + | '\u09bc'..'\u09c4' + | '\u09c7'..'\u09c8' + | '\u09cb'..'\u09cd' + | '\u09d7'..'\u09d7' + | '\u09dc'..'\u09dd' + | '\u09df'..'\u09e3' + | '\u09e6'..'\u09fa' + | '\u0a01'..'\u0a03' + | '\u0a05'..'\u0a0a' + | '\u0a0f'..'\u0a10' + | '\u0a13'..'\u0a28' + | '\u0a2a'..'\u0a30' + | '\u0a32'..'\u0a33' + | '\u0a35'..'\u0a36' + | '\u0a38'..'\u0a39' + | '\u0a3c'..'\u0a3c' + | '\u0a3e'..'\u0a42' + | '\u0a47'..'\u0a48' + | '\u0a4b'..'\u0a4d' + | '\u0a59'..'\u0a5c' + | '\u0a5e'..'\u0a5e' + | '\u0a66'..'\u0a74' + | '\u0a81'..'\u0a83' + | '\u0a85'..'\u0a8d' + | '\u0a8f'..'\u0a91' + | '\u0a93'..'\u0aa8' + | '\u0aaa'..'\u0ab0' + | '\u0ab2'..'\u0ab3' + | '\u0ab5'..'\u0ab9' + | '\u0abc'..'\u0ac5' + | '\u0ac7'..'\u0ac9' + | '\u0acb'..'\u0acd' + | '\u0ad0'..'\u0ad0' + | '\u0ae0'..'\u0ae3' + | '\u0ae6'..'\u0aef' + | '\u0af1'..'\u0af1' + | '\u0b01'..'\u0b03' + | '\u0b05'..'\u0b0c' + | '\u0b0f'..'\u0b10' + | '\u0b13'..'\u0b28' + | '\u0b2a'..'\u0b30' + | '\u0b32'..'\u0b33' + | '\u0b35'..'\u0b39' + | '\u0b3c'..'\u0b43' + | '\u0b47'..'\u0b48' + | '\u0b4b'..'\u0b4d' + | '\u0b56'..'\u0b57' + | '\u0b5c'..'\u0b5d' + | '\u0b5f'..'\u0b61' + | '\u0b66'..'\u0b71' + | '\u0b82'..'\u0b83' + | '\u0b85'..'\u0b8a' + | '\u0b8e'..'\u0b90' + | '\u0b92'..'\u0b95' + | '\u0b99'..'\u0b9a' + | '\u0b9c'..'\u0b9c' + | '\u0b9e'..'\u0b9f' + | '\u0ba3'..'\u0ba4' + | '\u0ba8'..'\u0baa' + | '\u0bae'..'\u0bb5' + | '\u0bb7'..'\u0bb9' + | '\u0bbe'..'\u0bc2' + | '\u0bc6'..'\u0bc8' + | '\u0bca'..'\u0bcd' + | '\u0bd7'..'\u0bd7' + | '\u0be7'..'\u0bfa' + | '\u0c01'..'\u0c03' + | '\u0c05'..'\u0c0c' + | '\u0c0e'..'\u0c10' + | '\u0c12'..'\u0c28' + | '\u0c2a'..'\u0c33' + | '\u0c35'..'\u0c39' + | '\u0c3e'..'\u0c44' + | '\u0c46'..'\u0c48' + | '\u0c4a'..'\u0c4d' + | '\u0c55'..'\u0c56' + | '\u0c60'..'\u0c61' + | '\u0c66'..'\u0c6f' + | '\u0c82'..'\u0c83' + | '\u0c85'..'\u0c8c' + | '\u0c8e'..'\u0c90' + | '\u0c92'..'\u0ca8' + | '\u0caa'..'\u0cb3' + | '\u0cb5'..'\u0cb9' + | '\u0cbc'..'\u0cc4' + | '\u0cc6'..'\u0cc8' + | '\u0cca'..'\u0ccd' + | '\u0cd5'..'\u0cd6' + | '\u0cde'..'\u0cde' + | '\u0ce0'..'\u0ce1' + | '\u0ce6'..'\u0cef' + | '\u0d02'..'\u0d03' + | '\u0d05'..'\u0d0c' + | '\u0d0e'..'\u0d10' + | '\u0d12'..'\u0d28' + | '\u0d2a'..'\u0d39' + | '\u0d3e'..'\u0d43' + | '\u0d46'..'\u0d48' + | '\u0d4a'..'\u0d4d' + | '\u0d57'..'\u0d57' + | '\u0d60'..'\u0d61' + | '\u0d66'..'\u0d6f' + | '\u0d82'..'\u0d83' + | '\u0d85'..'\u0d96' + | '\u0d9a'..'\u0db1' + | '\u0db3'..'\u0dbb' + | '\u0dbd'..'\u0dbd' + | '\u0dc0'..'\u0dc6' + | '\u0dca'..'\u0dca' + | '\u0dcf'..'\u0dd4' + | '\u0dd6'..'\u0dd6' + | '\u0dd8'..'\u0ddf' + | '\u0df2'..'\u0df3' + | '\u0e01'..'\u0e3a' + | '\u0e3f'..'\u0e4e' + | '\u0e50'..'\u0e59' + | '\u0e81'..'\u0e82' + | '\u0e84'..'\u0e84' + | '\u0e87'..'\u0e88' + | '\u0e8a'..'\u0e8a' + | '\u0e8d'..'\u0e8d' + | '\u0e94'..'\u0e97' + | '\u0e99'..'\u0e9f' + | '\u0ea1'..'\u0ea3' + | '\u0ea5'..'\u0ea5' + | '\u0ea7'..'\u0ea7' + | '\u0eaa'..'\u0eab' + | '\u0ead'..'\u0eb9' + | '\u0ebb'..'\u0ebd' + | '\u0ec0'..'\u0ec4' + | '\u0ec6'..'\u0ec6' + | '\u0ec8'..'\u0ecd' + | '\u0ed0'..'\u0ed9' + | '\u0edc'..'\u0edd' + | '\u0f00'..'\u0f03' + | '\u0f13'..'\u0f39' + | '\u0f3e'..'\u0f47' + | '\u0f49'..'\u0f6a' + | '\u0f71'..'\u0f84' + | '\u0f86'..'\u0f8b' + | '\u0f90'..'\u0f97' + | '\u0f99'..'\u0fbc' + | '\u0fbe'..'\u0fcc' + | '\u0fcf'..'\u0fcf' + | '\u1000'..'\u1021' + | '\u1023'..'\u1027' + | '\u1029'..'\u102a' + | '\u102c'..'\u1032' + | '\u1036'..'\u1039' + | '\u1040'..'\u1049' + | '\u1050'..'\u1059' + | '\u10a0'..'\u10c5' + | '\u10d0'..'\u10f8' + | '\u1100'..'\u1159' + | '\u115f'..'\u11a2' + | '\u11a8'..'\u11f9' + | '\u1200'..'\u1206' + | '\u1208'..'\u1246' + | '\u1248'..'\u1248' + | '\u124a'..'\u124d' + | '\u1250'..'\u1256' + | '\u1258'..'\u1258' + | '\u125a'..'\u125d' + | '\u1260'..'\u1286' + | '\u1288'..'\u1288' + | '\u128a'..'\u128d' + | '\u1290'..'\u12ae' + | '\u12b0'..'\u12b0' + | '\u12b2'..'\u12b5' + | '\u12b8'..'\u12be' + | '\u12c0'..'\u12c0' + | '\u12c2'..'\u12c5' + | '\u12c8'..'\u12ce' + | '\u12d0'..'\u12d6' + | '\u12d8'..'\u12ee' + | '\u12f0'..'\u130e' + | '\u1310'..'\u1310' + | '\u1312'..'\u1315' + | '\u1318'..'\u131e' + | '\u1320'..'\u1346' + | '\u1348'..'\u135a' + | '\u1369'..'\u137c' + | '\u13a0'..'\u13f4' + | '\u1401'..'\u166c' + | '\u166f'..'\u1676' + | '\u1681'..'\u169a' + | '\u16a0'..'\u16ea' + | '\u16ee'..'\u16f0' + | '\u1700'..'\u170c' + | '\u170e'..'\u1714' + | '\u1720'..'\u1734' + | '\u1740'..'\u1753' + | '\u1760'..'\u176c' + | '\u176e'..'\u1770' + | '\u1772'..'\u1773' + | '\u1780'..'\u17b3' + | '\u17b6'..'\u17d3' + | '\u17d7' + | '\u17db'..'\u17dd' + | '\u17e0'..'\u17e9' + | '\u17f0'..'\u17f9' + | '\u180b'..'\u180d' + | '\u1810'..'\u1819' + | '\u1820'..'\u1877' + | '\u1880'..'\u18a9' + | '\u1900'..'\u191c' + | '\u1920'..'\u192b' + | '\u1930'..'\u193b' + | '\u1940'..'\u1940' + | '\u1946'..'\u196d' + | '\u1970'..'\u1974' + | '\u19e0'..'\u19ff' + | '\u1d00'..'\u1d6b' + | '\u1e00'..'\u1e9b' + | '\u1ea0'..'\u1ef9' + | '\u1f00'..'\u1f15' + | '\u1f18'..'\u1f1d' + | '\u1f20'..'\u1f45' + | '\u1f48'..'\u1f4d' + | '\u1f50'..'\u1f57' + | '\u1f59'..'\u1f59' + | '\u1f5b'..'\u1f5b' + | '\u1f5d'..'\u1f5d' + | '\u1f5f'..'\u1f7d' + | '\u1f80'..'\u1fb4' + | '\u1fb6'..'\u1fbc' + | '\u1fbe' + | '\u1fc2'..'\u1fc4' + | '\u1fc6'..'\u1fcc' + | '\u1fd0'..'\u1fd3' + | '\u1fd6'..'\u1fdb' + | '\u1fe0'..'\u1fec' + | '\u1ff2'..'\u1ff4' + | '\u1ff6'..'\u1ffc' + | '\u2070'..'\u2071' + | '\u2074'..'\u2079' + | '\u207f'..'\u2089' + | '\u20a0'..'\u20b1' + | '\u20d0'..'\u20ea' + | '\u2100'..'\u213b' + | '\u213d'..'\u213f' + | '\u2145'..'\u214a' + | '\u2153'..'\u2183' + | '\u2195'..'\u2199' + | '\u219c'..'\u219f' + | '\u21a1'..'\u21a2' + | '\u21a4'..'\u21a5' + | '\u21a7'..'\u21ad' + | '\u21af'..'\u21cd' + | '\u21d0'..'\u21d1' + | '\u21d3' + | '\u21d5'..'\u21f3' + | '\u2300'..'\u2307' + | '\u230c'..'\u231f' + | '\u2322'..'\u2328' + | '\u232b'..'\u237b' + | '\u237d'..'\u239a' + | '\u23b7'..'\u23d0' + | '\u2400'..'\u2426' + | '\u2440'..'\u244a' + | '\u2460'..'\u25b6' + | '\u25b8'..'\u25c0' + | '\u25c2'..'\u25f7' + | '\u2600'..'\u2617' + | '\u2619'..'\u266e' + | '\u2670'..'\u267d' + | '\u2680'..'\u2691' + | '\u26a0'..'\u26a1' + | '\u2701'..'\u2704' + | '\u2706'..'\u2709' + | '\u270c'..'\u2727' + | '\u2729'..'\u274b' + | '\u274d'..'\u274d' + | '\u274f'..'\u2752' + | '\u2756'..'\u2756' + | '\u2758'..'\u275e' + | '\u2761'..'\u2767' + | '\u2776'..'\u2794' + | '\u2798'..'\u27af' + | '\u27b1'..'\u27be' + | '\u2800'..'\u28ff' + | '\u2b00'..'\u2b0d' + | '\u2e80'..'\u2e99' + | '\u2e9b'..'\u2ef3' + | '\u2f00'..'\u2fd5' + | '\u2ff0'..'\u2ffb' + | '\u3004'..'\u3007' + | '\u3012'..'\u3013' + | '\u3020'..'\u302f' + | '\u3031'..'\u303c' + | '\u303e'..'\u303f' + | '\u3041'..'\u3096' + | '\u3099'..'\u309a' + | '\u309d'..'\u309f' + | '\u30a1'..'\u30fa' + | '\u30fc'..'\u30ff' + | '\u3105'..'\u312c' + | '\u3131'..'\u318e' + | '\u3190'..'\u31b7' + | '\u31f0'..'\u321e' + | '\u3220'..'\u3243' + | '\u3250'..'\u327d' + | '\u327f'..'\u32fe' + | '\u3300'..'\u4db5' + | '\u4dc0'..'\u9fa5' + | '\ua000'..'\ua48c' + | '\ua490'..'\ua4c6' + | '\uac00'..'\ud7a3' + | '\uf900'..'\ufa2d' + | '\ufa30'..'\ufa6a' + | '\ufb00'..'\ufb06' + | '\ufb13'..'\ufb17' + | '\ufb1d'..'\ufb28' + | '\ufb2a'..'\ufb36' + | '\ufb38'..'\ufb3c' + | '\ufb3e'..'\ufb3e' + | '\ufb40'..'\ufb41' + | '\ufb43'..'\ufb44' + | '\ufb46'..'\ufbb1' + | '\ufbd3'..'\ufd3d' + | '\ufd50'..'\ufd8f' + | '\ufd92'..'\ufdc7' + | '\ufdf0'..'\ufdfd' + | '\ufe00'..'\ufe0f' + | '\ufe20'..'\ufe23' + | '\ufe69' + | '\ufe70'..'\ufe74' + | '\ufe76'..'\ufefc' + | '\uff04' + | '\uff10'..'\uff19' + | '\uff21'..'\uff3a' + | '\uff41'..'\uff5a' + | '\uff66'..'\uffbe' + | '\uffc2'..'\uffc7' + | '\uffca'..'\uffcf' + | '\uffd2'..'\uffd7' + | '\uffda'..'\uffdc' + | '\uffe0'..'\uffe1' + | '\uffe4'..'\uffe6' + | '\uffe8' + | '\uffed'..'\uffee' + ; + +// exclude ? 003F - wildcard +// exclude * 002A - wildcard +// exclude \ 005C - escape +// exclude : 003A - field indicator +// exclude ~ 00&E - fuzzy queries +// exclude > 003C - ranges +// exclude < 003E - range +// exclude . 002E +// exclude , 002C +// exclude +fragment +IN_WORD + : + '\u0021'..'\u0027' + | '\u002b' + | '\u002d' + | '\u002f'..'\u0039' + | '\u003b' + | '\u003d' + | '\u0040'..'\u005a' + | '\u005f' + | '\u0061'..'\u007a' + | '\u007c' + | '\u00a1'..'\u00a7' + | '\u00a9'..'\u00aa' + | '\u00ac' + | '\u00ae' + | '\u00b0'..'\u00b3' + | '\u00b5'..'\u00b7' + | '\u00b9'..'\u00ba' + | '\u00bc'..'\u0236' + | '\u0250'..'\u02c1' + | '\u02c6'..'\u02d1' + | '\u02e0'..'\u02e4' + | '\u02ee' + | '\u0300'..'\u0357' + | '\u035d'..'\u036f' + | '\u037a'..'\u037a' + | '\u037e'..'\u037e' + | '\u0386'..'\u038a' + | '\u038c'..'\u038c' + | '\u038e'..'\u03a1' + | '\u03a3'..'\u03ce' + | '\u03d0'..'\u03fb' + | '\u0400'..'\u0486' + | '\u0488'..'\u04ce' + | '\u04d0'..'\u04f5' + | '\u04f8'..'\u04f9' + | '\u0500'..'\u050f' + | '\u0531'..'\u0556' + | '\u0559'..'\u055f' + | '\u0561'..'\u0587' + | '\u0589'..'\u058a' + | '\u0591'..'\u05a1' + | '\u05a3'..'\u05b9' + | '\u05bb'..'\u05c4' + | '\u05d0'..'\u05ea' + | '\u05f0'..'\u05f4' + | '\u060c'..'\u0615' + | '\u061b'..'\u061b' + | '\u061f'..'\u061f' + | '\u0621'..'\u063a' + | '\u0640'..'\u0658' + | '\u0660'..'\u06dc' + | '\u06de'..'\u070d' + | '\u0710'..'\u074a' + | '\u074d'..'\u074f' + | '\u0780'..'\u07b1' + | '\u0901'..'\u0939' + | '\u093c'..'\u094d' + | '\u0950'..'\u0954' + | '\u0958'..'\u0970' + | '\u0981'..'\u0983' + | '\u0985'..'\u098c' + | '\u098f'..'\u0990' + | '\u0993'..'\u09a8' + | '\u09aa'..'\u09b0' + | '\u09b2'..'\u09b2' + | '\u09b6'..'\u09b9' + | '\u09bc'..'\u09c4' + | '\u09c7'..'\u09c8' + | '\u09cb'..'\u09cd' + | '\u09d7'..'\u09d7' + | '\u09dc'..'\u09dd' + | '\u09df'..'\u09e3' + | '\u09e6'..'\u09fa' + | '\u0a01'..'\u0a03' + | '\u0a05'..'\u0a0a' + | '\u0a0f'..'\u0a10' + | '\u0a13'..'\u0a28' + | '\u0a2a'..'\u0a30' + | '\u0a32'..'\u0a33' + | '\u0a35'..'\u0a36' + | '\u0a38'..'\u0a39' + | '\u0a3c'..'\u0a3c' + | '\u0a3e'..'\u0a42' + | '\u0a47'..'\u0a48' + | '\u0a4b'..'\u0a4d' + | '\u0a59'..'\u0a5c' + | '\u0a5e'..'\u0a5e' + | '\u0a66'..'\u0a74' + | '\u0a81'..'\u0a83' + | '\u0a85'..'\u0a8d' + | '\u0a8f'..'\u0a91' + | '\u0a93'..'\u0aa8' + | '\u0aaa'..'\u0ab0' + | '\u0ab2'..'\u0ab3' + | '\u0ab5'..'\u0ab9' + | '\u0abc'..'\u0ac5' + | '\u0ac7'..'\u0ac9' + | '\u0acb'..'\u0acd' + | '\u0ad0'..'\u0ad0' + | '\u0ae0'..'\u0ae3' + | '\u0ae6'..'\u0aef' + | '\u0af1'..'\u0af1' + | '\u0b01'..'\u0b03' + | '\u0b05'..'\u0b0c' + | '\u0b0f'..'\u0b10' + | '\u0b13'..'\u0b28' + | '\u0b2a'..'\u0b30' + | '\u0b32'..'\u0b33' + | '\u0b35'..'\u0b39' + | '\u0b3c'..'\u0b43' + | '\u0b47'..'\u0b48' + | '\u0b4b'..'\u0b4d' + | '\u0b56'..'\u0b57' + | '\u0b5c'..'\u0b5d' + | '\u0b5f'..'\u0b61' + | '\u0b66'..'\u0b71' + | '\u0b82'..'\u0b83' + | '\u0b85'..'\u0b8a' + | '\u0b8e'..'\u0b90' + | '\u0b92'..'\u0b95' + | '\u0b99'..'\u0b9a' + | '\u0b9c'..'\u0b9c' + | '\u0b9e'..'\u0b9f' + | '\u0ba3'..'\u0ba4' + | '\u0ba8'..'\u0baa' + | '\u0bae'..'\u0bb5' + | '\u0bb7'..'\u0bb9' + | '\u0bbe'..'\u0bc2' + | '\u0bc6'..'\u0bc8' + | '\u0bca'..'\u0bcd' + | '\u0bd7'..'\u0bd7' + | '\u0be7'..'\u0bfa' + | '\u0c01'..'\u0c03' + | '\u0c05'..'\u0c0c' + | '\u0c0e'..'\u0c10' + | '\u0c12'..'\u0c28' + | '\u0c2a'..'\u0c33' + | '\u0c35'..'\u0c39' + | '\u0c3e'..'\u0c44' + | '\u0c46'..'\u0c48' + | '\u0c4a'..'\u0c4d' + | '\u0c55'..'\u0c56' + | '\u0c60'..'\u0c61' + | '\u0c66'..'\u0c6f' + | '\u0c82'..'\u0c83' + | '\u0c85'..'\u0c8c' + | '\u0c8e'..'\u0c90' + | '\u0c92'..'\u0ca8' + | '\u0caa'..'\u0cb3' + | '\u0cb5'..'\u0cb9' + | '\u0cbc'..'\u0cc4' + | '\u0cc6'..'\u0cc8' + | '\u0cca'..'\u0ccd' + | '\u0cd5'..'\u0cd6' + | '\u0cde'..'\u0cde' + | '\u0ce0'..'\u0ce1' + | '\u0ce6'..'\u0cef' + | '\u0d02'..'\u0d03' + | '\u0d05'..'\u0d0c' + | '\u0d0e'..'\u0d10' + | '\u0d12'..'\u0d28' + | '\u0d2a'..'\u0d39' + | '\u0d3e'..'\u0d43' + | '\u0d46'..'\u0d48' + | '\u0d4a'..'\u0d4d' + | '\u0d57'..'\u0d57' + | '\u0d60'..'\u0d61' + | '\u0d66'..'\u0d6f' + | '\u0d82'..'\u0d83' + | '\u0d85'..'\u0d96' + | '\u0d9a'..'\u0db1' + | '\u0db3'..'\u0dbb' + | '\u0dbd'..'\u0dbd' + | '\u0dc0'..'\u0dc6' + | '\u0dca'..'\u0dca' + | '\u0dcf'..'\u0dd4' + | '\u0dd6'..'\u0dd6' + | '\u0dd8'..'\u0ddf' + | '\u0df2'..'\u0df4' + | '\u0e01'..'\u0e3a' + | '\u0e3f'..'\u0e5b' + | '\u0e81'..'\u0e82' + | '\u0e84'..'\u0e84' + | '\u0e87'..'\u0e88' + | '\u0e8a'..'\u0e8a' + | '\u0e8d'..'\u0e8d' + | '\u0e94'..'\u0e97' + | '\u0e99'..'\u0e9f' + | '\u0ea1'..'\u0ea3' + | '\u0ea5'..'\u0ea5' + | '\u0ea7'..'\u0ea7' + | '\u0eaa'..'\u0eab' + | '\u0ead'..'\u0eb9' + | '\u0ebb'..'\u0ebd' + | '\u0ec0'..'\u0ec4' + | '\u0ec6'..'\u0ec6' + | '\u0ec8'..'\u0ecd' + | '\u0ed0'..'\u0ed9' + | '\u0edc'..'\u0edd' + | '\u0f00'..'\u0f39' + | '\u0f3e'..'\u0f47' + | '\u0f49'..'\u0f6a' + | '\u0f71'..'\u0f8b' + | '\u0f90'..'\u0f97' + | '\u0f99'..'\u0fbc' + | '\u0fbe'..'\u0fcc' + | '\u0fcf'..'\u0fcf' + | '\u1000'..'\u1021' + | '\u1023'..'\u1027' + | '\u1029'..'\u102a' + | '\u102c'..'\u1032' + | '\u1036'..'\u1039' + | '\u1040'..'\u1059' + | '\u10a0'..'\u10c5' + | '\u10d0'..'\u10f8' + | '\u10fb'..'\u10fb' + | '\u1100'..'\u1159' + | '\u115f'..'\u11a2' + | '\u11a8'..'\u11f9' + | '\u1200'..'\u1206' + | '\u1208'..'\u1246' + | '\u1248'..'\u1248' + | '\u124a'..'\u124d' + | '\u1250'..'\u1256' + | '\u1258'..'\u1258' + | '\u125a'..'\u125d' + | '\u1260'..'\u1286' + | '\u1288'..'\u1288' + | '\u128a'..'\u128d' + | '\u1290'..'\u12ae' + | '\u12b0'..'\u12b0' + | '\u12b2'..'\u12b5' + | '\u12b8'..'\u12be' + | '\u12c0'..'\u12c0' + | '\u12c2'..'\u12c5' + | '\u12c8'..'\u12ce' + | '\u12d0'..'\u12d6' + | '\u12d8'..'\u12ee' + | '\u12f0'..'\u130e' + | '\u1310'..'\u1310' + | '\u1312'..'\u1315' + | '\u1318'..'\u131e' + | '\u1320'..'\u1346' + | '\u1348'..'\u135a' + | '\u1361'..'\u137c' + | '\u13a0'..'\u13f4' + | '\u1401'..'\u1676' + | '\u1681'..'\u169a' + | '\u16a0'..'\u16f0' + | '\u1700'..'\u170c' + | '\u170e'..'\u1714' + | '\u1720'..'\u1736' + | '\u1740'..'\u1753' + | '\u1760'..'\u176c' + | '\u176e'..'\u1770' + | '\u1772'..'\u1773' + | '\u1780'..'\u17b3' + | '\u17b6'..'\u17dd' + | '\u17e0'..'\u17e9' + | '\u17f0'..'\u17f9' + | '\u1800'..'\u180d' + | '\u1810'..'\u1819' + | '\u1820'..'\u1877' + | '\u1880'..'\u18a9' + | '\u1900'..'\u191c' + | '\u1920'..'\u192b' + | '\u1930'..'\u193b' + | '\u1940'..'\u1940' + | '\u1944'..'\u196d' + | '\u1970'..'\u1974' + | '\u19e0'..'\u19ff' + | '\u1d00'..'\u1d6b' + | '\u1e00'..'\u1e9b' + | '\u1ea0'..'\u1ef9' + | '\u1f00'..'\u1f15' + | '\u1f18'..'\u1f1d' + | '\u1f20'..'\u1f45' + | '\u1f48'..'\u1f4d' + | '\u1f50'..'\u1f57' + | '\u1f59'..'\u1f59' + | '\u1f5b'..'\u1f5b' + | '\u1f5d'..'\u1f5d' + | '\u1f5f'..'\u1f7d' + | '\u1f80'..'\u1fb4' + | '\u1fb6'..'\u1fbc' + | '\u1fbe' + | '\u1fc2'..'\u1fc4' + | '\u1fc6'..'\u1fcc' + | '\u1fd0'..'\u1fd3' + | '\u1fd6'..'\u1fdb' + | '\u1fe0'..'\u1fec' + | '\u1ff2'..'\u1ff4' + | '\u1ff6'..'\u1ffc' + | '\u2010'..'\u2017' + | '\u2020'..'\u2027' + | '\u2030'..'\u2038' + | '\u203b'..'\u2044' + | '\u2047'..'\u2054' + | '\u2057'..'\u2057' + | '\u2070'..'\u2071' + | '\u2074'..'\u207c' + | '\u207f'..'\u208c' + | '\u20a0'..'\u20b1' + | '\u20d0'..'\u20ea' + | '\u2100'..'\u213b' + | '\u213d'..'\u214b' + | '\u2153'..'\u2183' + | '\u2190'..'\u2328' + | '\u232b'..'\u23b3' + | '\u23b6'..'\u23d0' + | '\u2400'..'\u2426' + | '\u2440'..'\u244a' + | '\u2460'..'\u2617' + | '\u2619'..'\u267d' + | '\u2680'..'\u2691' + | '\u26a0'..'\u26a1' + | '\u2701'..'\u2704' + | '\u2706'..'\u2709' + | '\u270c'..'\u2727' + | '\u2729'..'\u274b' + | '\u274d'..'\u274d' + | '\u274f'..'\u2752' + | '\u2756'..'\u2756' + | '\u2758'..'\u275e' + | '\u2761'..'\u2767' + | '\u2776'..'\u2794' + | '\u2798'..'\u27af' + | '\u27b1'..'\u27be' + | '\u27d0'..'\u27e5' + | '\u27f0'..'\u2982' + | '\u2999'..'\u29d7' + | '\u29dc'..'\u29fb' + | '\u29fe'..'\u2b0d' + | '\u2e80'..'\u2e99' + | '\u2e9b'..'\u2ef3' + | '\u2f00'..'\u2fd5' + | '\u2ff0'..'\u2ffb' + | '\u3001'..'\u3007' + | '\u3012'..'\u3013' + | '\u301c' + | '\u3020'..'\u303f' + | '\u3041'..'\u3096' + | '\u3099'..'\u309a' + | '\u309d'..'\u30ff' + | '\u3105'..'\u312c' + | '\u3131'..'\u318e' + | '\u3190'..'\u31b7' + | '\u31f0'..'\u321e' + | '\u3220'..'\u3243' + | '\u3250'..'\u327d' + | '\u327f'..'\u32fe' + | '\u3300'..'\u4db5' + | '\u4dc0'..'\u9fa5' + | '\ua000'..'\ua48c' + | '\ua490'..'\ua4c6' + | '\uac00'..'\ud7a3' + | '\uf900'..'\ufa2d' + | '\ufa30'..'\ufa6a' + | '\ufb00'..'\ufb06' + | '\ufb13'..'\ufb17' + | '\ufb1d'..'\ufb36' + | '\ufb38'..'\ufb3c' + | '\ufb3e'..'\ufb3e' + | '\ufb40'..'\ufb41' + | '\ufb43'..'\ufb44' + | '\ufb46'..'\ufbb1' + | '\ufbd3'..'\ufd3d' + | '\ufd50'..'\ufd8f' + | '\ufd92'..'\ufdc7' + | '\ufdf0'..'\ufdfd' + | '\ufe00'..'\ufe0f' + | '\ufe20'..'\ufe23' + | '\ufe30'..'\ufe34' + | '\ufe45'..'\ufe46' + | '\ufe49'..'\ufe52' + | '\ufe54'..'\ufe58' + | '\ufe5f'..'\ufe66' + | '\ufe68'..'\ufe6b' + | '\ufe70'..'\ufe74' + | '\ufe76'..'\ufefc' + | '\uff01'..'\uff07' + | '\uff0a'..'\uff3a' + | '\uff3c' + | '\uff3f' + | '\uff41'..'\uff5a' + | '\uff5c' + | '\uff5e' + | '\uff61' + | '\uff64'..'\uffbe' + | '\uffc2'..'\uffc7' + | '\uffca'..'\uffcf' + | '\uffd2'..'\uffd7' + | '\uffda'..'\uffdc' + | '\uffe0'..'\uffe2' + | '\uffe4'..'\uffe6' + | '\uffe8'..'\uffee' + ; + + +/* + * Standard white space + * White space may be escaped by \ in some tokens + */ + + +WS + : + ( + ' ' + | '\t' + | '\r' + | '\n' + | '\u000C' // FF + | '\u00a0' // Additional Unicode space from Character.isSpaceChar() + | '\u1680' + | '\u180e' + | '\u2000' .. '\u200b' + | '\u2028' .. '\u2029' + | '\u202f' + | '\u205f' + | '\u3000' + )+ + { $channel = HIDDEN; } + ; diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTS.tokens b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTS.tokens new file mode 100644 index 0000000000..421ec5be8d --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTS.tokens @@ -0,0 +1,104 @@ +AMP=4 +AND=5 +AT=6 +BAR=7 +BOOST=8 +CARAT=9 +COLON=10 +COMMA=11 +CONJUNCTION=12 +DATETIME=13 +DAY=14 +DECIMAL_INTEGER_LITERAL=15 +DECIMAL_NUMERAL=16 +DEFAULT=17 +DIGIT=18 +DISJUNCTION=19 +DOLLAR=20 +DOT=21 +DOTDOT=22 +E=23 +EQUALS=24 +EXACT_PHRASE=25 +EXACT_TERM=26 +EXCLAMATION=27 +EXCLUDE=28 +EXCLUSIVE=29 +EXPONENT=30 +FG_EXACT_PHRASE=31 +FG_EXACT_TERM=32 +FG_PHRASE=33 +FG_PROXIMITY=34 +FG_RANGE=35 +FG_SYNONYM=36 +FG_TERM=37 +FIELD_CONJUNCTION=38 +FIELD_DEFAULT=39 +FIELD_DISJUNCTION=40 +FIELD_EXCLUDE=41 +FIELD_GROUP=42 +FIELD_MANDATORY=43 +FIELD_NEGATION=44 +FIELD_OPTIONAL=45 +FIELD_REF=46 +FLOATING_POINT_LITERAL=47 +FS=48 +FTS=49 +FTSPHRASE=50 +FTSPRE=51 +FTSWILD=52 +FTSWORD=53 +FUZZY=54 +F_ESC=55 +F_HEX=56 +F_URI_ALPHA=57 +F_URI_DIGIT=58 +F_URI_ESC=59 +F_URI_OTHER=60 +GT=61 +HOUR=62 +ID=63 +INCLUSIVE=64 +IN_WORD=65 +LCURL=66 +LPAREN=67 +LSQUARE=68 +LT=69 +MANDATORY=70 +MILLIS=71 +MINUS=72 +MINUTE=73 +MONTH=74 +NAME_SPACE=75 +NEGATION=76 +NON_ZERO_DIGIT=77 +NOT=78 +NOW=79 +OPTIONAL=80 +OR=81 +PERCENT=82 +PHRASE=83 +PLUS=84 +PREFIX=85 +PROXIMITY=86 +QUALIFIER=87 +QUESTION_MARK=88 +RANGE=89 +RCURL=90 +RPAREN=91 +RSQUARE=92 +SECOND=93 +SIGNED_INTEGER=94 +SPECIFICDATETIME=95 +STAR=96 +START_WORD=97 +SYNONYM=98 +TEMPLATE=99 +TERM=100 +TILDA=101 +TO=102 +UNIT=103 +URI=104 +WS=105 +YEAR=106 +ZERO_DIGIT=107 diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTSLexer.java b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTSLexer.java new file mode 100644 index 0000000000..0864f88cf9 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTSLexer.java @@ -0,0 +1,22788 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +// $ANTLR 3.5.2 W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g 2015-06-18 19:37:56 + +package org.alfresco.repo.search.impl.parsers; + + +import org.antlr.runtime.*; +import java.util.Stack; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; + +@SuppressWarnings("all") +public class FTSLexer extends Lexer { + public static final int EOF=-1; + public static final int AMP=4; + public static final int AND=5; + public static final int AT=6; + public static final int BAR=7; + public static final int BOOST=8; + public static final int CARAT=9; + public static final int COLON=10; + public static final int COMMA=11; + public static final int CONJUNCTION=12; + public static final int DATETIME=13; + public static final int DAY=14; + public static final int DECIMAL_INTEGER_LITERAL=15; + public static final int DECIMAL_NUMERAL=16; + public static final int DEFAULT=17; + public static final int DIGIT=18; + public static final int DISJUNCTION=19; + public static final int DOLLAR=20; + public static final int DOT=21; + public static final int DOTDOT=22; + public static final int E=23; + public static final int EQUALS=24; + public static final int EXACT_PHRASE=25; + public static final int EXACT_TERM=26; + public static final int EXCLAMATION=27; + public static final int EXCLUDE=28; + public static final int EXCLUSIVE=29; + public static final int EXPONENT=30; + public static final int FG_EXACT_PHRASE=31; + public static final int FG_EXACT_TERM=32; + public static final int FG_PHRASE=33; + public static final int FG_PROXIMITY=34; + public static final int FG_RANGE=35; + public static final int FG_SYNONYM=36; + public static final int FG_TERM=37; + public static final int FIELD_CONJUNCTION=38; + public static final int FIELD_DEFAULT=39; + public static final int FIELD_DISJUNCTION=40; + public static final int FIELD_EXCLUDE=41; + public static final int FIELD_GROUP=42; + public static final int FIELD_MANDATORY=43; + public static final int FIELD_NEGATION=44; + public static final int FIELD_OPTIONAL=45; + public static final int FIELD_REF=46; + public static final int FLOATING_POINT_LITERAL=47; + public static final int FS=48; + public static final int FTS=49; + public static final int FTSPHRASE=50; + public static final int FTSPRE=51; + public static final int FTSWILD=52; + public static final int FTSWORD=53; + public static final int FUZZY=54; + public static final int F_ESC=55; + public static final int F_HEX=56; + public static final int F_URI_ALPHA=57; + public static final int F_URI_DIGIT=58; + public static final int F_URI_ESC=59; + public static final int F_URI_OTHER=60; + public static final int GT=61; + public static final int HOUR=62; + public static final int ID=63; + public static final int INCLUSIVE=64; + public static final int IN_WORD=65; + public static final int LCURL=66; + public static final int LPAREN=67; + public static final int LSQUARE=68; + public static final int LT=69; + public static final int MANDATORY=70; + public static final int MILLIS=71; + public static final int MINUS=72; + public static final int MINUTE=73; + public static final int MONTH=74; + public static final int NAME_SPACE=75; + public static final int NEGATION=76; + public static final int NON_ZERO_DIGIT=77; + public static final int NOT=78; + public static final int NOW=79; + public static final int OPTIONAL=80; + public static final int OR=81; + public static final int PERCENT=82; + public static final int PHRASE=83; + public static final int PLUS=84; + public static final int PREFIX=85; + public static final int PROXIMITY=86; + public static final int QUALIFIER=87; + public static final int QUESTION_MARK=88; + public static final int RANGE=89; + public static final int RCURL=90; + public static final int RPAREN=91; + public static final int RSQUARE=92; + public static final int SECOND=93; + public static final int SIGNED_INTEGER=94; + public static final int SPECIFICDATETIME=95; + public static final int STAR=96; + public static final int START_WORD=97; + public static final int SYNONYM=98; + public static final int TEMPLATE=99; + public static final int TERM=100; + public static final int TILDA=101; + public static final int TO=102; + public static final int UNIT=103; + public static final int URI=104; + public static final int WS=105; + public static final int YEAR=106; + public static final int ZERO_DIGIT=107; + + List tokens = new ArrayList(); + public void emit(Token token) { + state.token = token; + tokens.add(token); + } + public Token nextToken() { + nextTokenImpl(); + if ( tokens.size()==0 ) { + return getEOFToken(); + } + return (Token)tokens.remove(0); + } + + public Token nextTokenImpl() { + while (true) + { + state.token = null; + state.channel = Token.DEFAULT_CHANNEL; + state.tokenStartCharIndex = input.index(); + state.tokenStartCharPositionInLine = input.getCharPositionInLine(); + state.tokenStartLine = input.getLine(); + state.text = null; + if ( input.LA(1)==CharStream.EOF ) + { + return getEOFToken(); + } + try + { + mTokens(); + if ( state.token==null ) + { + emit(); + } + else if ( state.token==Token.SKIP_TOKEN ) + { + continue; + } + return state.token; + } + catch (RecognitionException re) + { + throw new FTSQueryException(getErrorString(re), re); + } + } + } + + public String getErrorString(RecognitionException e) + { + String hdr = getErrorHeader(e); + String msg = getErrorMessage(e, this.getTokenNames()); + return hdr+" "+msg; + } + + + // delegates + // delegators + public Lexer[] getDelegates() { + return new Lexer[] {}; + } + + public FTSLexer() {} + public FTSLexer(CharStream input) { + this(input, new RecognizerSharedState()); + } + public FTSLexer(CharStream input, RecognizerSharedState state) { + super(input,state); + } + @Override public String getGrammarFileName() { return "W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g"; } + + // $ANTLR start "FTSPHRASE" + public final void mFTSPHRASE() throws RecognitionException { + try { + int _type = FTSPHRASE; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:935:9: ( '\"' ( F_ESC |~ ( '\\\\' | '\"' ) )* '\"' | '\\'' ( F_ESC |~ ( '\\\\' | '\\'' ) )* '\\'' ) + int alt3=2; + int LA3_0 = input.LA(1); + if ( (LA3_0=='\"') ) { + alt3=1; + } + else if ( (LA3_0=='\'') ) { + alt3=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + NoViableAltException nvae = + new NoViableAltException("", 3, 0, input); + throw nvae; + } + + switch (alt3) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:936:9: '\"' ( F_ESC |~ ( '\\\\' | '\"' ) )* '\"' + { + match('\"'); if (state.failed) return; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:937:9: ( F_ESC |~ ( '\\\\' | '\"' ) )* + loop1: + while (true) { + int alt1=3; + int LA1_0 = input.LA(1); + if ( (LA1_0=='\\') ) { + alt1=1; + } + else if ( ((LA1_0 >= '\u0000' && LA1_0 <= '!')||(LA1_0 >= '#' && LA1_0 <= '[')||(LA1_0 >= ']' && LA1_0 <= '\uFFFF')) ) { + alt1=2; + } + + switch (alt1) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:938:17: F_ESC + { + mF_ESC(); if (state.failed) return; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:940:17: ~ ( '\\\\' | '\"' ) + { + if ( (input.LA(1) >= '\u0000' && input.LA(1) <= '!')||(input.LA(1) >= '#' && input.LA(1) <= '[')||(input.LA(1) >= ']' && input.LA(1) <= '\uFFFF') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + break loop1; + } + } + + match('\"'); if (state.failed) return; + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:946:11: '\\'' ( F_ESC |~ ( '\\\\' | '\\'' ) )* '\\'' + { + match('\''); if (state.failed) return; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:947:9: ( F_ESC |~ ( '\\\\' | '\\'' ) )* + loop2: + while (true) { + int alt2=3; + int LA2_0 = input.LA(1); + if ( (LA2_0=='\\') ) { + alt2=1; + } + else if ( ((LA2_0 >= '\u0000' && LA2_0 <= '&')||(LA2_0 >= '(' && LA2_0 <= '[')||(LA2_0 >= ']' && LA2_0 <= '\uFFFF')) ) { + alt2=2; + } + + switch (alt2) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:948:17: F_ESC + { + mF_ESC(); if (state.failed) return; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:950:17: ~ ( '\\\\' | '\\'' ) + { + if ( (input.LA(1) >= '\u0000' && input.LA(1) <= '&')||(input.LA(1) >= '(' && input.LA(1) <= '[')||(input.LA(1) >= ']' && input.LA(1) <= '\uFFFF') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + break loop2; + } + } + + match('\''); if (state.failed) return; + } + break; + + } + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "FTSPHRASE" + + // $ANTLR start "URI" + public final void mURI() throws RecognitionException { + try { + int _type = URI; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:964:9: ( '{' ( ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER )=> ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER )+ COLON )? ( ( ( '//' )=> '//' ) ( ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON )=> ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON ) )* )? ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON | '/' )* ( '?' ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON | '/' | '?' )* )? ( '#' ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON | '/' | '?' | '#' )* )? '}' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:965:9: '{' ( ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER )=> ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER )+ COLON )? ( ( ( '//' )=> '//' ) ( ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON )=> ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON ) )* )? ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON | '/' )* ( '?' ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON | '/' | '?' )* )? ( '#' ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON | '/' | '?' | '#' )* )? '}' + { + match('{'); if (state.failed) return; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:966:9: ( ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER )=> ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER )+ COLON )? + int alt5=2; + alt5 = dfa5.predict(input); + switch (alt5) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:967:17: ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER )=> ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER )+ COLON + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:973:17: ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER )+ + int cnt4=0; + loop4: + while (true) { + int alt4=2; + int LA4_0 = input.LA(1); + if ( (LA4_0=='!'||LA4_0=='$'||(LA4_0 >= '&' && LA4_0 <= '.')||(LA4_0 >= '0' && LA4_0 <= '9')||LA4_0==';'||LA4_0=='='||(LA4_0 >= '@' && LA4_0 <= '[')||LA4_0==']'||LA4_0=='_'||(LA4_0 >= 'a' && LA4_0 <= 'z')||LA4_0=='~') ) { + alt4=1; + } + + switch (alt4) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='!'||input.LA(1)=='$'||(input.LA(1) >= '&' && input.LA(1) <= '.')||(input.LA(1) >= '0' && input.LA(1) <= '9')||input.LA(1)==';'||input.LA(1)=='='||(input.LA(1) >= '@' && input.LA(1) <= '[')||input.LA(1)==']'||input.LA(1)=='_'||(input.LA(1) >= 'a' && input.LA(1) <= 'z')||input.LA(1)=='~' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + if ( cnt4 >= 1 ) break loop4; + if (state.backtracking>0) {state.failed=true; return;} + EarlyExitException eee = new EarlyExitException(4, input); + throw eee; + } + cnt4++; + } + + mCOLON(); if (state.failed) return; + + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:980:9: ( ( ( '//' )=> '//' ) ( ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON )=> ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON ) )* )? + int alt7=2; + int LA7_0 = input.LA(1); + if ( (LA7_0=='/') ) { + int LA7_1 = input.LA(2); + if ( (LA7_1=='/') ) { + int LA7_3 = input.LA(3); + if ( (synpred2_FTS()) ) { + alt7=1; + } + } + } + switch (alt7) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:981:17: ( ( '//' )=> '//' ) ( ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON )=> ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON ) )* + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:981:17: ( ( '//' )=> '//' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:981:19: ( '//' )=> '//' + { + match("//"); if (state.failed) return; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:982:17: ( ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON )=> ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON ) )* + loop6: + while (true) { + int alt6=2; + int LA6_0 = input.LA(1); + if ( (LA6_0=='!'||LA6_0=='$'||(LA6_0 >= '&' && LA6_0 <= '.')||(LA6_0 >= '0' && LA6_0 <= ';')||LA6_0=='='||(LA6_0 >= '@' && LA6_0 <= '[')||LA6_0==']'||LA6_0=='_'||(LA6_0 >= 'a' && LA6_0 <= 'z')||LA6_0=='~') ) { + int LA6_1 = input.LA(2); + if ( (synpred3_FTS()) ) { + alt6=1; + } + + } + + switch (alt6) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:983:25: ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON )=> ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON ) + { + if ( input.LA(1)=='!'||input.LA(1)=='$'||(input.LA(1) >= '&' && input.LA(1) <= '.')||(input.LA(1) >= '0' && input.LA(1) <= ';')||input.LA(1)=='='||(input.LA(1) >= '@' && input.LA(1) <= '[')||input.LA(1)==']'||input.LA(1)=='_'||(input.LA(1) >= 'a' && input.LA(1) <= 'z')||input.LA(1)=='~' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + break loop6; + } + } + + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:998:9: ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON | '/' )* + loop8: + while (true) { + int alt8=2; + int LA8_0 = input.LA(1); + if ( (LA8_0=='!'||LA8_0=='$'||(LA8_0 >= '&' && LA8_0 <= ';')||LA8_0=='='||(LA8_0 >= '@' && LA8_0 <= '[')||LA8_0==']'||LA8_0=='_'||(LA8_0 >= 'a' && LA8_0 <= 'z')||LA8_0=='~') ) { + alt8=1; + } + + switch (alt8) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='!'||input.LA(1)=='$'||(input.LA(1) >= '&' && input.LA(1) <= ';')||input.LA(1)=='='||(input.LA(1) >= '@' && input.LA(1) <= '[')||input.LA(1)==']'||input.LA(1)=='_'||(input.LA(1) >= 'a' && input.LA(1) <= 'z')||input.LA(1)=='~' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + break loop8; + } + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1005:9: ( '?' ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON | '/' | '?' )* )? + int alt10=2; + int LA10_0 = input.LA(1); + if ( (LA10_0=='?') ) { + alt10=1; + } + switch (alt10) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1006:17: '?' ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON | '/' | '?' )* + { + match('?'); if (state.failed) return; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1007:17: ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON | '/' | '?' )* + loop9: + while (true) { + int alt9=2; + int LA9_0 = input.LA(1); + if ( (LA9_0=='!'||LA9_0=='$'||(LA9_0 >= '&' && LA9_0 <= ';')||LA9_0=='='||(LA9_0 >= '?' && LA9_0 <= '[')||LA9_0==']'||LA9_0=='_'||(LA9_0 >= 'a' && LA9_0 <= 'z')||LA9_0=='~') ) { + alt9=1; + } + + switch (alt9) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='!'||input.LA(1)=='$'||(input.LA(1) >= '&' && input.LA(1) <= ';')||input.LA(1)=='='||(input.LA(1) >= '?' && input.LA(1) <= '[')||input.LA(1)==']'||input.LA(1)=='_'||(input.LA(1) >= 'a' && input.LA(1) <= 'z')||input.LA(1)=='~' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + break loop9; + } + } + + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1016:9: ( '#' ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON | '/' | '?' | '#' )* )? + int alt12=2; + int LA12_0 = input.LA(1); + if ( (LA12_0=='#') ) { + alt12=1; + } + switch (alt12) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1017:17: '#' ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON | '/' | '?' | '#' )* + { + match('#'); if (state.failed) return; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1018:17: ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON | '/' | '?' | '#' )* + loop11: + while (true) { + int alt11=2; + int LA11_0 = input.LA(1); + if ( (LA11_0=='!'||(LA11_0 >= '#' && LA11_0 <= '$')||(LA11_0 >= '&' && LA11_0 <= ';')||LA11_0=='='||(LA11_0 >= '?' && LA11_0 <= '[')||LA11_0==']'||LA11_0=='_'||(LA11_0 >= 'a' && LA11_0 <= 'z')||LA11_0=='~') ) { + alt11=1; + } + + switch (alt11) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='!'||(input.LA(1) >= '#' && input.LA(1) <= '$')||(input.LA(1) >= '&' && input.LA(1) <= ';')||input.LA(1)=='='||(input.LA(1) >= '?' && input.LA(1) <= '[')||input.LA(1)==']'||input.LA(1)=='_'||(input.LA(1) >= 'a' && input.LA(1) <= 'z')||input.LA(1)=='~' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + break loop11; + } + } + + } + break; + + } + + match('}'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "URI" + + // $ANTLR start "F_URI_ALPHA" + public final void mF_URI_ALPHA() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1034:9: ( 'A' .. 'Z' | 'a' .. 'z' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( (input.LA(1) >= 'A' && input.LA(1) <= 'Z')||(input.LA(1) >= 'a' && input.LA(1) <= 'z') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "F_URI_ALPHA" + + // $ANTLR start "F_URI_DIGIT" + public final void mF_URI_DIGIT() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1041:9: ( '0' .. '9' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "F_URI_DIGIT" + + // $ANTLR start "F_URI_ESC" + public final void mF_URI_ESC() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1047:9: ( '%' F_HEX F_HEX ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1048:9: '%' F_HEX F_HEX + { + match('%'); if (state.failed) return; + mF_HEX(); if (state.failed) return; + + mF_HEX(); if (state.failed) return; + + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "F_URI_ESC" + + // $ANTLR start "F_URI_OTHER" + public final void mF_URI_OTHER() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1053:9: ( '-' | '.' | '_' | '~' | '[' | ']' | '@' | '!' | '$' | '&' | '\\'' | '(' | ')' | '*' | '+' | ',' | ';' | '=' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='!'||input.LA(1)=='$'||(input.LA(1) >= '&' && input.LA(1) <= '.')||input.LA(1)==';'||input.LA(1)=='='||input.LA(1)=='@'||input.LA(1)=='['||input.LA(1)==']'||input.LA(1)=='_'||input.LA(1)=='~' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "F_URI_OTHER" + + // $ANTLR start "DATETIME" + public final void mDATETIME() throws RecognitionException { + try { + int _type = DATETIME; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1084:9: ( ( SPECIFICDATETIME | NOW ) ( FS UNIT )? ( ( PLUS | MINUS ) ( DIGIT )+ UNIT )* ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1085:10: ( SPECIFICDATETIME | NOW ) ( FS UNIT )? ( ( PLUS | MINUS ) ( DIGIT )+ UNIT )* + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1085:10: ( SPECIFICDATETIME | NOW ) + int alt13=2; + int LA13_0 = input.LA(1); + if ( ((LA13_0 >= '0' && LA13_0 <= '9')) ) { + alt13=1; + } + else if ( (LA13_0=='N'||LA13_0=='n') ) { + alt13=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + NoViableAltException nvae = + new NoViableAltException("", 13, 0, input); + throw nvae; + } + + switch (alt13) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1085:11: SPECIFICDATETIME + { + mSPECIFICDATETIME(); if (state.failed) return; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1085:30: NOW + { + mNOW(); if (state.failed) return; + + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1085:35: ( FS UNIT )? + int alt14=2; + int LA14_0 = input.LA(1); + if ( (LA14_0=='/') ) { + alt14=1; + } + switch (alt14) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1085:36: FS UNIT + { + mFS(); if (state.failed) return; + + mUNIT(); if (state.failed) return; + + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1085:46: ( ( PLUS | MINUS ) ( DIGIT )+ UNIT )* + loop16: + while (true) { + int alt16=2; + int LA16_0 = input.LA(1); + if ( (LA16_0=='+'||LA16_0=='-') ) { + alt16=1; + } + + switch (alt16) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1085:48: ( PLUS | MINUS ) ( DIGIT )+ UNIT + { + if ( input.LA(1)=='+'||input.LA(1)=='-' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1085:61: ( DIGIT )+ + int cnt15=0; + loop15: + while (true) { + int alt15=2; + int LA15_0 = input.LA(1); + if ( ((LA15_0 >= '0' && LA15_0 <= '9')) ) { + alt15=1; + } + + switch (alt15) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + if ( cnt15 >= 1 ) break loop15; + if (state.backtracking>0) {state.failed=true; return;} + EarlyExitException eee = new EarlyExitException(15, input); + throw eee; + } + cnt15++; + } + + mUNIT(); if (state.failed) return; + + } + break; + + default : + break loop16; + } + } + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DATETIME" + + // $ANTLR start "UNIT" + public final void mUNIT() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1085:9: ( ( YEAR | MONTH | DAY | HOUR | MINUTE | SECOND | MILLIS ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1086:9: ( YEAR | MONTH | DAY | HOUR | MINUTE | SECOND | MILLIS ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1086:9: ( YEAR | MONTH | DAY | HOUR | MINUTE | SECOND | MILLIS ) + int alt17=7; + switch ( input.LA(1) ) { + case 'Y': + case 'y': + { + alt17=1; + } + break; + case 'M': + case 'm': + { + int LA17_2 = input.LA(2); + if ( (LA17_2=='O'||LA17_2=='o') ) { + alt17=2; + } + else if ( (LA17_2=='I'||LA17_2=='i') ) { + int LA17_7 = input.LA(3); + if ( (LA17_7=='N'||LA17_7=='n') ) { + alt17=5; + } + else if ( (LA17_7=='L'||LA17_7=='l') ) { + alt17=7; + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 3 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 17, 7, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 17, 2, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case 'D': + case 'd': + { + alt17=3; + } + break; + case 'H': + case 'h': + { + alt17=4; + } + break; + case 'S': + case 's': + { + alt17=6; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return;} + NoViableAltException nvae = + new NoViableAltException("", 17, 0, input); + throw nvae; + } + switch (alt17) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1086:10: YEAR + { + mYEAR(); if (state.failed) return; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1086:17: MONTH + { + mMONTH(); if (state.failed) return; + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1086:25: DAY + { + mDAY(); if (state.failed) return; + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1086:31: HOUR + { + mHOUR(); if (state.failed) return; + + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1086:38: MINUTE + { + mMINUTE(); if (state.failed) return; + + } + break; + case 6 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1086:47: SECOND + { + mSECOND(); if (state.failed) return; + + } + break; + case 7 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1086:56: MILLIS + { + mMILLIS(); if (state.failed) return; + + } + break; + + } + + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "UNIT" + + // $ANTLR start "SPECIFICDATETIME" + public final void mSPECIFICDATETIME() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1090:9: ( DIGIT DIGIT DIGIT DIGIT ( '-' DIGIT DIGIT ( '-' DIGIT DIGIT ( 'T' ( DIGIT DIGIT ( ':' DIGIT DIGIT ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? )? )? )? )? )? )? ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1091:12: DIGIT DIGIT DIGIT DIGIT ( '-' DIGIT DIGIT ( '-' DIGIT DIGIT ( 'T' ( DIGIT DIGIT ( ':' DIGIT DIGIT ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? )? )? )? )? )? )? + { + mDIGIT(); if (state.failed) return; + + mDIGIT(); if (state.failed) return; + + mDIGIT(); if (state.failed) return; + + mDIGIT(); if (state.failed) return; + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:15: ( '-' DIGIT DIGIT ( '-' DIGIT DIGIT ( 'T' ( DIGIT DIGIT ( ':' DIGIT DIGIT ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? )? )? )? )? )? )? + int alt26=2; + int LA26_0 = input.LA(1); + if ( (LA26_0=='-') ) { + alt26=1; + } + switch (alt26) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:17: '-' DIGIT DIGIT ( '-' DIGIT DIGIT ( 'T' ( DIGIT DIGIT ( ':' DIGIT DIGIT ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? )? )? )? )? )? + { + match('-'); if (state.failed) return; + mDIGIT(); if (state.failed) return; + + mDIGIT(); if (state.failed) return; + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:33: ( '-' DIGIT DIGIT ( 'T' ( DIGIT DIGIT ( ':' DIGIT DIGIT ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? )? )? )? )? )? + int alt25=2; + int LA25_0 = input.LA(1); + if ( (LA25_0=='-') ) { + alt25=1; + } + switch (alt25) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:35: '-' DIGIT DIGIT ( 'T' ( DIGIT DIGIT ( ':' DIGIT DIGIT ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? )? )? )? )? + { + match('-'); if (state.failed) return; + mDIGIT(); if (state.failed) return; + + mDIGIT(); if (state.failed) return; + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:51: ( 'T' ( DIGIT DIGIT ( ':' DIGIT DIGIT ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? )? )? )? )? + int alt24=2; + int LA24_0 = input.LA(1); + if ( (LA24_0=='T') ) { + alt24=1; + } + switch (alt24) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:53: 'T' ( DIGIT DIGIT ( ':' DIGIT DIGIT ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? )? )? )? + { + match('T'); if (state.failed) return; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:57: ( DIGIT DIGIT ( ':' DIGIT DIGIT ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? )? )? )? + int alt23=2; + int LA23_0 = input.LA(1); + if ( ((LA23_0 >= '0' && LA23_0 <= '9')) ) { + alt23=1; + } + switch (alt23) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:58: DIGIT DIGIT ( ':' DIGIT DIGIT ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? )? )? + { + mDIGIT(); if (state.failed) return; + + mDIGIT(); if (state.failed) return; + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:70: ( ':' DIGIT DIGIT ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? )? )? + int alt22=2; + int LA22_0 = input.LA(1); + if ( (LA22_0==':') ) { + alt22=1; + } + switch (alt22) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:72: ':' DIGIT DIGIT ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? )? + { + match(':'); if (state.failed) return; + mDIGIT(); if (state.failed) return; + + mDIGIT(); if (state.failed) return; + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:88: ( ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? )? + int alt21=2; + int LA21_0 = input.LA(1); + if ( (LA21_0==':') ) { + alt21=1; + } + switch (alt21) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:90: ':' DIGIT DIGIT ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? + { + match(':'); if (state.failed) return; + mDIGIT(); if (state.failed) return; + + mDIGIT(); if (state.failed) return; + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:106: ( '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? )? + int alt20=2; + int LA20_0 = input.LA(1); + if ( (LA20_0=='.') ) { + alt20=1; + } + switch (alt20) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:108: '.' DIGIT DIGIT DIGIT ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? + { + match('.'); if (state.failed) return; + mDIGIT(); if (state.failed) return; + + mDIGIT(); if (state.failed) return; + + mDIGIT(); if (state.failed) return; + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:130: ( 'Z' | ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) )? + int alt19=3; + int LA19_0 = input.LA(1); + if ( (LA19_0=='Z') ) { + alt19=1; + } + else if ( (LA19_0=='+'||LA19_0=='-') ) { + alt19=2; + } + switch (alt19) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:132: 'Z' + { + match('Z'); if (state.failed) return; + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:138: ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:138: ( ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:139: ( '+' | '-' ) DIGIT DIGIT ( ':' DIGIT DIGIT )? + { + if ( input.LA(1)=='+'||input.LA(1)=='-' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + mDIGIT(); if (state.failed) return; + + mDIGIT(); if (state.failed) return; + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:164: ( ':' DIGIT DIGIT )? + int alt18=2; + int LA18_0 = input.LA(1); + if ( (LA18_0==':') ) { + alt18=1; + } + switch (alt18) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1092:166: ':' DIGIT DIGIT + { + match(':'); if (state.failed) return; + mDIGIT(); if (state.failed) return; + + mDIGIT(); if (state.failed) return; + + } + break; + + } + + } + + } + break; + + } + + } + break; + + } + + } + break; + + } + + } + break; + + } + + } + break; + + } + + } + break; + + } + + } + break; + + } + + } + break; + + } + + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "SPECIFICDATETIME" + + // $ANTLR start "NOW" + public final void mNOW() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1096:9: ( ( 'N' | 'n' ) ( 'O' | 'o' ) ( 'W' | 'w' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1097:12: ( 'N' | 'n' ) ( 'O' | 'o' ) ( 'W' | 'w' ) + { + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='W'||input.LA(1)=='w' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "NOW" + + // $ANTLR start "YEAR" + public final void mYEAR() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1101:9: ( ( 'Y' | 'y' ) ( 'E' | 'e' ) ( 'A' | 'a' ) ( 'R' | 'r' ) ( 'S' | 's' )? ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1102:11: ( 'Y' | 'y' ) ( 'E' | 'e' ) ( 'A' | 'a' ) ( 'R' | 'r' ) ( 'S' | 's' )? + { + if ( input.LA(1)=='Y'||input.LA(1)=='y' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='A'||input.LA(1)=='a' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1102:51: ( 'S' | 's' )? + int alt27=2; + int LA27_0 = input.LA(1); + if ( (LA27_0=='S'||LA27_0=='s') ) { + alt27=1; + } + switch (alt27) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "YEAR" + + // $ANTLR start "MONTH" + public final void mMONTH() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1106:9: ( ( 'M' | 'm' ) ( 'O' | 'o' ) ( 'N' | 'n' ) ( 'T' | 't' ) ( 'H' | 'h' ) ( 'S' | 's' )? ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1107:11: ( 'M' | 'm' ) ( 'O' | 'o' ) ( 'N' | 'n' ) ( 'T' | 't' ) ( 'H' | 'h' ) ( 'S' | 's' )? + { + if ( input.LA(1)=='M'||input.LA(1)=='m' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='T'||input.LA(1)=='t' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='H'||input.LA(1)=='h' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1107:61: ( 'S' | 's' )? + int alt28=2; + int LA28_0 = input.LA(1); + if ( (LA28_0=='S'||LA28_0=='s') ) { + alt28=1; + } + switch (alt28) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "MONTH" + + // $ANTLR start "DAY" + public final void mDAY() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1111:9: ( ( 'D' | 'd' ) ( 'A' | 'a' ) ( 'Y' | 'y' ) ( 'S' | 's' )? | ( 'D' | 'd' ) ( 'A' | 'a' ) ( 'T' | 't' ) ( 'E' | 'e' ) ) + int alt30=2; + int LA30_0 = input.LA(1); + if ( (LA30_0=='D'||LA30_0=='d') ) { + int LA30_1 = input.LA(2); + if ( (LA30_1=='A'||LA30_1=='a') ) { + int LA30_2 = input.LA(3); + if ( (LA30_2=='Y'||LA30_2=='y') ) { + alt30=1; + } + else if ( (LA30_2=='T'||LA30_2=='t') ) { + alt30=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 3 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 30, 2, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 30, 1, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + NoViableAltException nvae = + new NoViableAltException("", 30, 0, input); + throw nvae; + } + + switch (alt30) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1112:11: ( 'D' | 'd' ) ( 'A' | 'a' ) ( 'Y' | 'y' ) ( 'S' | 's' )? + { + if ( input.LA(1)=='D'||input.LA(1)=='d' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='A'||input.LA(1)=='a' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='Y'||input.LA(1)=='y' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1112:41: ( 'S' | 's' )? + int alt29=2; + int LA29_0 = input.LA(1); + if ( (LA29_0=='S'||LA29_0=='s') ) { + alt29=1; + } + switch (alt29) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1113:11: ( 'D' | 'd' ) ( 'A' | 'a' ) ( 'T' | 't' ) ( 'E' | 'e' ) + { + if ( input.LA(1)=='D'||input.LA(1)=='d' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='A'||input.LA(1)=='a' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='T'||input.LA(1)=='t' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DAY" + + // $ANTLR start "HOUR" + public final void mHOUR() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1117:9: ( ( 'H' | 'h' ) ( 'O' | 'o' ) ( 'U' | 'u' ) ( 'R' | 'r' ) ( 'S' | 's' )? ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1118:11: ( 'H' | 'h' ) ( 'O' | 'o' ) ( 'U' | 'u' ) ( 'R' | 'r' ) ( 'S' | 's' )? + { + if ( input.LA(1)=='H'||input.LA(1)=='h' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='U'||input.LA(1)=='u' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1118:51: ( 'S' | 's' )? + int alt31=2; + int LA31_0 = input.LA(1); + if ( (LA31_0=='S'||LA31_0=='s') ) { + alt31=1; + } + switch (alt31) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "HOUR" + + // $ANTLR start "MINUTE" + public final void mMINUTE() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1122:9: ( ( 'M' | 'm' ) ( 'I' | 'i' ) ( 'N' | 'n' ) ( 'U' | 'u' ) ( 'T' | 't' ) ( 'E' | 'e' ) ( 'S' | 's' )? ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1123:11: ( 'M' | 'm' ) ( 'I' | 'i' ) ( 'N' | 'n' ) ( 'U' | 'u' ) ( 'T' | 't' ) ( 'E' | 'e' ) ( 'S' | 's' )? + { + if ( input.LA(1)=='M'||input.LA(1)=='m' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='I'||input.LA(1)=='i' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='U'||input.LA(1)=='u' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='T'||input.LA(1)=='t' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1123:71: ( 'S' | 's' )? + int alt32=2; + int LA32_0 = input.LA(1); + if ( (LA32_0=='S'||LA32_0=='s') ) { + alt32=1; + } + switch (alt32) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "MINUTE" + + // $ANTLR start "SECOND" + public final void mSECOND() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1127:9: ( ( 'S' | 's' ) ( 'E' | 'e' ) ( 'C' | 'c' ) ( 'O' | 'o' ) ( 'N' | 'n' ) ( 'D' | 'd' ) ( 'S' | 's' )? ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1128:11: ( 'S' | 's' ) ( 'E' | 'e' ) ( 'C' | 'c' ) ( 'O' | 'o' ) ( 'N' | 'n' ) ( 'D' | 'd' ) ( 'S' | 's' )? + { + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='C'||input.LA(1)=='c' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='D'||input.LA(1)=='d' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1128:71: ( 'S' | 's' )? + int alt33=2; + int LA33_0 = input.LA(1); + if ( (LA33_0=='S'||LA33_0=='s') ) { + alt33=1; + } + switch (alt33) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "SECOND" + + // $ANTLR start "MILLIS" + public final void mMILLIS() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1132:9: ( ( 'M' | 'm' ) ( 'I' | 'i' ) ( 'L' | 'l' ) ( 'L' | 'l' ) ( 'I' | 'i' ) ( 'S' | 's' ) ( 'E' | 'e' ) ( 'C' | 'c' ) ( 'O' | 'o' ) ( 'N' | 'n' ) ( 'D' | 'd' ) ( 'S' | 's' )? | ( 'M' | 'm' ) ( 'I' | 'i' ) ( 'L' | 'l' ) ( 'L' | 'l' ) ( 'I' | 'i' ) ( 'S' | 's' )? ) + int alt36=2; + int LA36_0 = input.LA(1); + if ( (LA36_0=='M'||LA36_0=='m') ) { + int LA36_1 = input.LA(2); + if ( (LA36_1=='I'||LA36_1=='i') ) { + int LA36_2 = input.LA(3); + if ( (LA36_2=='L'||LA36_2=='l') ) { + int LA36_3 = input.LA(4); + if ( (LA36_3=='L'||LA36_3=='l') ) { + int LA36_4 = input.LA(5); + if ( (LA36_4=='I'||LA36_4=='i') ) { + int LA36_5 = input.LA(6); + if ( (LA36_5=='S'||LA36_5=='s') ) { + int LA36_6 = input.LA(7); + if ( (LA36_6=='E'||LA36_6=='e') ) { + alt36=1; + } + + else { + alt36=2; + } + + } + + else { + alt36=2; + } + + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 5 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 36, 4, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 36, 3, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 3 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 36, 2, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 36, 1, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + NoViableAltException nvae = + new NoViableAltException("", 36, 0, input); + throw nvae; + } + + switch (alt36) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1133:11: ( 'M' | 'm' ) ( 'I' | 'i' ) ( 'L' | 'l' ) ( 'L' | 'l' ) ( 'I' | 'i' ) ( 'S' | 's' ) ( 'E' | 'e' ) ( 'C' | 'c' ) ( 'O' | 'o' ) ( 'N' | 'n' ) ( 'D' | 'd' ) ( 'S' | 's' )? + { + if ( input.LA(1)=='M'||input.LA(1)=='m' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='I'||input.LA(1)=='i' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='L'||input.LA(1)=='l' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='L'||input.LA(1)=='l' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='I'||input.LA(1)=='i' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='C'||input.LA(1)=='c' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='D'||input.LA(1)=='d' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1133:121: ( 'S' | 's' )? + int alt34=2; + int LA34_0 = input.LA(1); + if ( (LA34_0=='S'||LA34_0=='s') ) { + alt34=1; + } + switch (alt34) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1134:11: ( 'M' | 'm' ) ( 'I' | 'i' ) ( 'L' | 'l' ) ( 'L' | 'l' ) ( 'I' | 'i' ) ( 'S' | 's' )? + { + if ( input.LA(1)=='M'||input.LA(1)=='m' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='I'||input.LA(1)=='i' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='L'||input.LA(1)=='l' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='L'||input.LA(1)=='l' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='I'||input.LA(1)=='i' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1134:61: ( 'S' | 's' )? + int alt35=2; + int LA35_0 = input.LA(1); + if ( (LA35_0=='S'||LA35_0=='s') ) { + alt35=1; + } + switch (alt35) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='S'||input.LA(1)=='s' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + } + break; + + } + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "MILLIS" + + // $ANTLR start "FS" + public final void mFS() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1138:9: ( '/' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1139:9: '/' + { + match('/'); if (state.failed) return; + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "FS" + + // $ANTLR start "OR" + public final void mOR() throws RecognitionException { + try { + int _type = OR; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1148:9: ( ( 'O' | 'o' ) ( 'R' | 'r' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1149:9: ( 'O' | 'o' ) ( 'R' | 'r' ) + { + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='R'||input.LA(1)=='r' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "OR" + + // $ANTLR start "AND" + public final void mAND() throws RecognitionException { + try { + int _type = AND; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1160:9: ( ( 'A' | 'a' ) ( 'N' | 'n' ) ( 'D' | 'd' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1161:9: ( 'A' | 'a' ) ( 'N' | 'n' ) ( 'D' | 'd' ) + { + if ( input.LA(1)=='A'||input.LA(1)=='a' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='D'||input.LA(1)=='d' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "AND" + + // $ANTLR start "NOT" + public final void mNOT() throws RecognitionException { + try { + int _type = NOT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1176:9: ( ( 'N' | 'n' ) ( 'O' | 'o' ) ( 'T' | 't' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1177:9: ( 'N' | 'n' ) ( 'O' | 'o' ) ( 'T' | 't' ) + { + if ( input.LA(1)=='N'||input.LA(1)=='n' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='T'||input.LA(1)=='t' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "NOT" + + // $ANTLR start "TILDA" + public final void mTILDA() throws RecognitionException { + try { + int _type = TILDA; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1192:9: ( '~' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1193:9: '~' + { + match('~'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "TILDA" + + // $ANTLR start "LPAREN" + public final void mLPAREN() throws RecognitionException { + try { + int _type = LPAREN; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1197:9: ( '(' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1198:9: '(' + { + match('('); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "LPAREN" + + // $ANTLR start "RPAREN" + public final void mRPAREN() throws RecognitionException { + try { + int _type = RPAREN; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1202:9: ( ')' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1203:9: ')' + { + match(')'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "RPAREN" + + // $ANTLR start "PLUS" + public final void mPLUS() throws RecognitionException { + try { + int _type = PLUS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1207:9: ( '+' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1208:9: '+' + { + match('+'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "PLUS" + + // $ANTLR start "MINUS" + public final void mMINUS() throws RecognitionException { + try { + int _type = MINUS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1212:9: ( '-' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1213:9: '-' + { + match('-'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "MINUS" + + // $ANTLR start "COLON" + public final void mCOLON() throws RecognitionException { + try { + int _type = COLON; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1217:9: ( ':' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1218:9: ':' + { + match(':'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "COLON" + + // $ANTLR start "STAR" + public final void mSTAR() throws RecognitionException { + try { + int _type = STAR; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1222:9: ( '*' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1223:9: '*' + { + match('*'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "STAR" + + // $ANTLR start "DOTDOT" + public final void mDOTDOT() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1228:9: ( '..' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1229:9: '..' + { + match(".."); if (state.failed) return; + + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DOTDOT" + + // $ANTLR start "DOT" + public final void mDOT() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1234:9: ( '.' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1235:9: '.' + { + match('.'); if (state.failed) return; + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DOT" + + // $ANTLR start "AMP" + public final void mAMP() throws RecognitionException { + try { + int _type = AMP; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1239:9: ( '&' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1240:9: '&' + { + match('&'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "AMP" + + // $ANTLR start "EXCLAMATION" + public final void mEXCLAMATION() throws RecognitionException { + try { + int _type = EXCLAMATION; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1244:9: ( '!' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1245:9: '!' + { + match('!'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "EXCLAMATION" + + // $ANTLR start "BAR" + public final void mBAR() throws RecognitionException { + try { + int _type = BAR; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1249:9: ( '|' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1250:9: '|' + { + match('|'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "BAR" + + // $ANTLR start "EQUALS" + public final void mEQUALS() throws RecognitionException { + try { + int _type = EQUALS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1254:9: ( '=' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1255:9: '=' + { + match('='); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "EQUALS" + + // $ANTLR start "QUESTION_MARK" + public final void mQUESTION_MARK() throws RecognitionException { + try { + int _type = QUESTION_MARK; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1259:9: ( '?' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1260:9: '?' + { + match('?'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "QUESTION_MARK" + + // $ANTLR start "LCURL" + public final void mLCURL() throws RecognitionException { + try { + int _type = LCURL; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1264:9: ( '{' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1265:9: '{' + { + match('{'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "LCURL" + + // $ANTLR start "RCURL" + public final void mRCURL() throws RecognitionException { + try { + int _type = RCURL; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1269:9: ( '}' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1270:9: '}' + { + match('}'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "RCURL" + + // $ANTLR start "LSQUARE" + public final void mLSQUARE() throws RecognitionException { + try { + int _type = LSQUARE; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1274:9: ( '[' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1275:9: '[' + { + match('['); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "LSQUARE" + + // $ANTLR start "RSQUARE" + public final void mRSQUARE() throws RecognitionException { + try { + int _type = RSQUARE; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1279:9: ( ']' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1280:9: ']' + { + match(']'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "RSQUARE" + + // $ANTLR start "TO" + public final void mTO() throws RecognitionException { + try { + int _type = TO; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1284:9: ( ( 'T' | 't' ) ( 'O' | 'o' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1285:9: ( 'T' | 't' ) ( 'O' | 'o' ) + { + if ( input.LA(1)=='T'||input.LA(1)=='t' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + if ( input.LA(1)=='O'||input.LA(1)=='o' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "TO" + + // $ANTLR start "COMMA" + public final void mCOMMA() throws RecognitionException { + try { + int _type = COMMA; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1296:9: ( ',' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1297:9: ',' + { + match(','); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "COMMA" + + // $ANTLR start "CARAT" + public final void mCARAT() throws RecognitionException { + try { + int _type = CARAT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1301:9: ( '^' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1302:9: '^' + { + match('^'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "CARAT" + + // $ANTLR start "DOLLAR" + public final void mDOLLAR() throws RecognitionException { + try { + int _type = DOLLAR; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1306:9: ( '$' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1307:9: '$' + { + match('$'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DOLLAR" + + // $ANTLR start "GT" + public final void mGT() throws RecognitionException { + try { + int _type = GT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1311:9: ( '>' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1312:9: '>' + { + match('>'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "GT" + + // $ANTLR start "LT" + public final void mLT() throws RecognitionException { + try { + int _type = LT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1316:9: ( '<' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1317:9: '<' + { + match('<'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "LT" + + // $ANTLR start "AT" + public final void mAT() throws RecognitionException { + try { + int _type = AT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1321:9: ( '@' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1322:9: '@' + { + match('@'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "AT" + + // $ANTLR start "PERCENT" + public final void mPERCENT() throws RecognitionException { + try { + int _type = PERCENT; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1326:9: ( '%' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1327:9: '%' + { + match('%'); if (state.failed) return; + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "PERCENT" + + // $ANTLR start "ID" + public final void mID() throws RecognitionException { + try { + int _type = ID; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1342:9: ( ( ( '0' .. '9' ) ( '0' .. '9' | '$' | '#' | F_ESC )* )? ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' | '#' | F_ESC )* ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1343:9: ( ( '0' .. '9' ) ( '0' .. '9' | '$' | '#' | F_ESC )* )? ( 'a' .. 'z' | 'A' .. 'Z' | '_' ) ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' | '#' | F_ESC )* + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1343:9: ( ( '0' .. '9' ) ( '0' .. '9' | '$' | '#' | F_ESC )* )? + int alt38=2; + int LA38_0 = input.LA(1); + if ( ((LA38_0 >= '0' && LA38_0 <= '9')) ) { + alt38=1; + } + switch (alt38) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1344:17: ( '0' .. '9' ) ( '0' .. '9' | '$' | '#' | F_ESC )* + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1345:17: ( '0' .. '9' | '$' | '#' | F_ESC )* + loop37: + while (true) { + int alt37=5; + switch ( input.LA(1) ) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + alt37=1; + } + break; + case '$': + { + alt37=2; + } + break; + case '#': + { + alt37=3; + } + break; + case '\\': + { + alt37=4; + } + break; + } + switch (alt37) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1345:19: '0' .. '9' + { + matchRange('0','9'); if (state.failed) return; + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1345:30: '$' + { + match('$'); if (state.failed) return; + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1345:36: '#' + { + match('#'); if (state.failed) return; + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1345:42: F_ESC + { + mF_ESC(); if (state.failed) return; + + } + break; + + default : + break loop37; + } + } + + } + break; + + } + + if ( (input.LA(1) >= 'A' && input.LA(1) <= 'Z')||input.LA(1)=='_'||(input.LA(1) >= 'a' && input.LA(1) <= 'z') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1348:9: ( 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_' | '$' | '#' | F_ESC )* + loop39: + while (true) { + int alt39=8; + switch ( input.LA(1) ) { + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + { + alt39=1; + } + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + { + alt39=2; + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + alt39=3; + } + break; + case '_': + { + alt39=4; + } + break; + case '$': + { + alt39=5; + } + break; + case '#': + { + alt39=6; + } + break; + case '\\': + { + alt39=7; + } + break; + } + switch (alt39) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1348:11: 'a' .. 'z' + { + matchRange('a','z'); if (state.failed) return; + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1348:22: 'A' .. 'Z' + { + matchRange('A','Z'); if (state.failed) return; + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1348:33: '0' .. '9' + { + matchRange('0','9'); if (state.failed) return; + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1348:44: '_' + { + match('_'); if (state.failed) return; + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1348:50: '$' + { + match('$'); if (state.failed) return; + } + break; + case 6 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1348:56: '#' + { + match('#'); if (state.failed) return; + } + break; + case 7 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1348:62: F_ESC + { + mF_ESC(); if (state.failed) return; + + } + break; + + default : + break loop39; + } + } + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "ID" + + // $ANTLR start "DECIMAL_INTEGER_LITERAL" + public final void mDECIMAL_INTEGER_LITERAL() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1351:9: () + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1352:9: + { + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DECIMAL_INTEGER_LITERAL" + + // $ANTLR start "FLOATING_POINT_LITERAL" + public final void mFLOATING_POINT_LITERAL() throws RecognitionException { + try { + int _type = FLOATING_POINT_LITERAL; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1355:9: ( ( PLUS | MINUS )? ( ( DIGIT )+ ({...}? => DOT ( ( DIGIT )+ ( EXPONENT |{...}? => DOT |) | EXPONENT |) | ( EXPONENT |) ) | DOT ( ( DIGIT )+ ( EXPONENT |{...}?{...}? => DOT |) |{...}? => '.' |) ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1356:10: ( PLUS | MINUS )? ( ( DIGIT )+ ({...}? => DOT ( ( DIGIT )+ ( EXPONENT |{...}? => DOT |) | EXPONENT |) | ( EXPONENT |) ) | DOT ( ( DIGIT )+ ( EXPONENT |{...}?{...}? => DOT |) |{...}? => '.' |) ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1356:10: ( PLUS | MINUS )? + int alt40=2; + int LA40_0 = input.LA(1); + if ( (LA40_0=='+'||LA40_0=='-') ) { + alt40=1; + } + switch (alt40) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='+'||input.LA(1)=='-' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1357:10: ( ( DIGIT )+ ({...}? => DOT ( ( DIGIT )+ ( EXPONENT |{...}? => DOT |) | EXPONENT |) | ( EXPONENT |) ) | DOT ( ( DIGIT )+ ( EXPONENT |{...}?{...}? => DOT |) |{...}? => '.' |) ) + int alt50=2; + int LA50_0 = input.LA(1); + if ( ((LA50_0 >= '0' && LA50_0 <= '9')) ) { + alt50=1; + } + else if ( (LA50_0=='.') ) { + alt50=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + NoViableAltException nvae = + new NoViableAltException("", 50, 0, input); + throw nvae; + } + + switch (alt50) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1358:17: ( DIGIT )+ ({...}? => DOT ( ( DIGIT )+ ( EXPONENT |{...}? => DOT |) | EXPONENT |) | ( EXPONENT |) ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1358:17: ( DIGIT )+ + int cnt41=0; + loop41: + while (true) { + int alt41=2; + int LA41_0 = input.LA(1); + if ( ((LA41_0 >= '0' && LA41_0 <= '9')) ) { + alt41=1; + } + + switch (alt41) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + if ( cnt41 >= 1 ) break loop41; + if (state.backtracking>0) {state.failed=true; return;} + EarlyExitException eee = new EarlyExitException(41, input); + throw eee; + } + cnt41++; + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1359:17: ({...}? => DOT ( ( DIGIT )+ ( EXPONENT |{...}? => DOT |) | EXPONENT |) | ( EXPONENT |) ) + int alt46=2; + int LA46_0 = input.LA(1); + if ( (LA46_0=='.') && ((input.LA(2) != '.'))) { + alt46=1; + } + + switch (alt46) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1360:25: {...}? => DOT ( ( DIGIT )+ ( EXPONENT |{...}? => DOT |) | EXPONENT |) + { + if ( !((input.LA(2) != '.')) ) { + if (state.backtracking>0) {state.failed=true; return;} + throw new FailedPredicateException(input, "FLOATING_POINT_LITERAL", "input.LA(2) != '.'"); + } + mDOT(); if (state.failed) return; + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1361:25: ( ( DIGIT )+ ( EXPONENT |{...}? => DOT |) | EXPONENT |) + int alt44=3; + switch ( input.LA(1) ) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + alt44=1; + } + break; + case 'E': + case 'e': + { + alt44=2; + } + break; + default: + alt44=3; + } + switch (alt44) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1362:33: ( DIGIT )+ ( EXPONENT |{...}? => DOT |) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1362:33: ( DIGIT )+ + int cnt42=0; + loop42: + while (true) { + int alt42=2; + int LA42_0 = input.LA(1); + if ( ((LA42_0 >= '0' && LA42_0 <= '9')) ) { + alt42=1; + } + + switch (alt42) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + if ( cnt42 >= 1 ) break loop42; + if (state.backtracking>0) {state.failed=true; return;} + EarlyExitException eee = new EarlyExitException(42, input); + throw eee; + } + cnt42++; + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1363:33: ( EXPONENT |{...}? => DOT |) + int alt43=3; + int LA43_0 = input.LA(1); + if ( (LA43_0=='E'||LA43_0=='e') ) { + alt43=1; + } + else if ( (LA43_0=='.') && ((input.LA(2) != '.'))) { + alt43=2; + } + + switch (alt43) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1364:37: EXPONENT + { + mEXPONENT(); if (state.failed) return; + + if ( state.backtracking==0 ) {_type = FLOATING_POINT_LITERAL; } + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1367:37: {...}? => DOT + { + if ( !((input.LA(2) != '.')) ) { + if (state.backtracking>0) {state.failed=true; return;} + throw new FailedPredicateException(input, "FLOATING_POINT_LITERAL", "input.LA(2) != '.'"); + } + mDOT(); if (state.failed) return; + + if ( state.backtracking==0 ) { + int index = getText().indexOf('.'); + + CommonToken digits1 = new CommonToken(input, DECIMAL_INTEGER_LITERAL, Token.DEFAULT_CHANNEL, state.tokenStartCharPositionInLine, state.tokenStartCharPositionInLine+index-1); + emit(digits1); + + CommonToken dot1 = new CommonToken(input, DOT, Token.DEFAULT_CHANNEL, state.tokenStartCharPositionInLine+index, state.tokenStartCharPositionInLine+index); + emit(dot1); + + CommonToken digits2 = new CommonToken(input, DECIMAL_INTEGER_LITERAL, Token.DEFAULT_CHANNEL, state.tokenStartCharPositionInLine+index+1, state.tokenStartCharPositionInLine + getText().length() -2); + emit(digits2); + + CommonToken dot2 = new CommonToken(input, DOT, Token.DEFAULT_CHANNEL, state.tokenStartCharPositionInLine + getText().length() -1, state.tokenStartCharPositionInLine + getText().length() -1); + emit(dot2); + + } + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1385:37: + { + if ( state.backtracking==0 ) {_type = FLOATING_POINT_LITERAL; } + } + break; + + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1388:33: EXPONENT + { + mEXPONENT(); if (state.failed) return; + + if ( state.backtracking==0 ) {_type = FLOATING_POINT_LITERAL; } + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1391:33: + { + if ( state.backtracking==0 ) {_type = FLOATING_POINT_LITERAL; } + } + break; + + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1394:25: ( EXPONENT |) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1394:25: ( EXPONENT |) + int alt45=2; + int LA45_0 = input.LA(1); + if ( (LA45_0=='E'||LA45_0=='e') ) { + alt45=1; + } + + else { + alt45=2; + } + + switch (alt45) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1395:33: EXPONENT + { + mEXPONENT(); if (state.failed) return; + + if ( state.backtracking==0 ) {_type = FLOATING_POINT_LITERAL; } + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1398:33: + { + if ( state.backtracking==0 ) {_type = DECIMAL_INTEGER_LITERAL; } + } + break; + + } + + } + break; + + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1404:17: DOT ( ( DIGIT )+ ( EXPONENT |{...}?{...}? => DOT |) |{...}? => '.' |) + { + mDOT(); if (state.failed) return; + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1405:17: ( ( DIGIT )+ ( EXPONENT |{...}?{...}? => DOT |) |{...}? => '.' |) + int alt49=3; + int LA49_0 = input.LA(1); + if ( ((LA49_0 >= '0' && LA49_0 <= '9')) ) { + alt49=1; + } + else if ( (LA49_0=='.') && ((input.LA(2) != '.'))) { + alt49=2; + } + + switch (alt49) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1406:25: ( DIGIT )+ ( EXPONENT |{...}?{...}? => DOT |) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1406:25: ( DIGIT )+ + int cnt47=0; + loop47: + while (true) { + int alt47=2; + int LA47_0 = input.LA(1); + if ( ((LA47_0 >= '0' && LA47_0 <= '9')) ) { + alt47=1; + } + + switch (alt47) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + if ( cnt47 >= 1 ) break loop47; + if (state.backtracking>0) {state.failed=true; return;} + EarlyExitException eee = new EarlyExitException(47, input); + throw eee; + } + cnt47++; + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1407:25: ( EXPONENT |{...}?{...}? => DOT |) + int alt48=3; + int LA48_0 = input.LA(1); + if ( (LA48_0=='E'||LA48_0=='e') ) { + alt48=1; + } + else if ( (LA48_0=='.') && ((input.LA(2) != '.'))) { + alt48=2; + } + + switch (alt48) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1408:29: EXPONENT + { + mEXPONENT(); if (state.failed) return; + + if ( state.backtracking==0 ) {_type = FLOATING_POINT_LITERAL; } + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1411:29: {...}?{...}? => DOT + { + if ( !((getText().startsWith("."))) ) { + if (state.backtracking>0) {state.failed=true; return;} + throw new FailedPredicateException(input, "FLOATING_POINT_LITERAL", "$text.startsWith(\".\")"); + } + if ( !((input.LA(2) != '.')) ) { + if (state.backtracking>0) {state.failed=true; return;} + throw new FailedPredicateException(input, "FLOATING_POINT_LITERAL", "input.LA(2) != '.'"); + } + mDOT(); if (state.failed) return; + + if ( state.backtracking==0 ) { + + CommonToken dot1 = new CommonToken(input, DOT, Token.DEFAULT_CHANNEL, state.tokenStartCharPositionInLine, state.tokenStartCharPositionInLine); + emit(dot1); + + CommonToken digits = new CommonToken(input, DECIMAL_INTEGER_LITERAL, Token.DEFAULT_CHANNEL, state.tokenStartCharPositionInLine+1, state.tokenStartCharPositionInLine + getText().length() -2); + emit(digits); + + CommonToken dot2 = new CommonToken(input, DOT, Token.DEFAULT_CHANNEL, state.tokenStartCharPositionInLine + getText().length() -1, state.tokenStartCharPositionInLine + getText().length() -1); + emit(dot2); + + } + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1426:29: + { + if ( state.backtracking==0 ) {_type = FLOATING_POINT_LITERAL; } + } + break; + + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1430:25: {...}? => '.' + { + if ( !((input.LA(2) != '.')) ) { + if (state.backtracking>0) {state.failed=true; return;} + throw new FailedPredicateException(input, "FLOATING_POINT_LITERAL", "input.LA(2) != '.'"); + } + match('.'); if (state.failed) return; + if ( state.backtracking==0 ) {_type = DOTDOT; } + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1433:25: + { + if ( state.backtracking==0 ) {_type = DOT; } + } + break; + + } + + } + break; + + } + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "FLOATING_POINT_LITERAL" + + // $ANTLR start "DECIMAL_NUMERAL" + public final void mDECIMAL_NUMERAL() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1462:9: ( ZERO_DIGIT | NON_ZERO_DIGIT ( DIGIT )* ) + int alt52=2; + int LA52_0 = input.LA(1); + if ( (LA52_0=='0') ) { + alt52=1; + } + else if ( ((LA52_0 >= '1' && LA52_0 <= '9')) ) { + alt52=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + NoViableAltException nvae = + new NoViableAltException("", 52, 0, input); + throw nvae; + } + + switch (alt52) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1463:9: ZERO_DIGIT + { + mZERO_DIGIT(); if (state.failed) return; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1464:11: NON_ZERO_DIGIT ( DIGIT )* + { + mNON_ZERO_DIGIT(); if (state.failed) return; + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1464:26: ( DIGIT )* + loop51: + while (true) { + int alt51=2; + int LA51_0 = input.LA(1); + if ( ((LA51_0 >= '0' && LA51_0 <= '9')) ) { + alt51=1; + } + + switch (alt51) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + break loop51; + } + } + + } + break; + + } + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DECIMAL_NUMERAL" + + // $ANTLR start "DIGIT" + public final void mDIGIT() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1466:9: ( ZERO_DIGIT | NON_ZERO_DIGIT ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "DIGIT" + + // $ANTLR start "ZERO_DIGIT" + public final void mZERO_DIGIT() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1473:9: ( '0' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1474:9: '0' + { + match('0'); if (state.failed) return; + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "ZERO_DIGIT" + + // $ANTLR start "NON_ZERO_DIGIT" + public final void mNON_ZERO_DIGIT() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1479:9: ( '1' .. '9' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( (input.LA(1) >= '1' && input.LA(1) <= '9') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "NON_ZERO_DIGIT" + + // $ANTLR start "E" + public final void mE() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1485:9: ( ( 'e' | 'E' ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='E'||input.LA(1)=='e' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "E" + + // $ANTLR start "EXPONENT" + public final void mEXPONENT() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1494:9: ( E SIGNED_INTEGER ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1495:9: E SIGNED_INTEGER + { + mE(); if (state.failed) return; + + mSIGNED_INTEGER(); if (state.failed) return; + + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "EXPONENT" + + // $ANTLR start "SIGNED_INTEGER" + public final void mSIGNED_INTEGER() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1500:9: ( ( PLUS | MINUS )? ( DIGIT )+ ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1501:9: ( PLUS | MINUS )? ( DIGIT )+ + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1501:9: ( PLUS | MINUS )? + int alt53=2; + int LA53_0 = input.LA(1); + if ( (LA53_0=='+'||LA53_0=='-') ) { + alt53=1; + } + switch (alt53) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='+'||input.LA(1)=='-' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1505:9: ( DIGIT )+ + int cnt54=0; + loop54: + while (true) { + int alt54=2; + int LA54_0 = input.LA(1); + if ( ((LA54_0 >= '0' && LA54_0 <= '9')) ) { + alt54=1; + } + + switch (alt54) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + if ( cnt54 >= 1 ) break loop54; + if (state.backtracking>0) {state.failed=true; return;} + EarlyExitException eee = new EarlyExitException(54, input); + throw eee; + } + cnt54++; + } + + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "SIGNED_INTEGER" + + // $ANTLR start "FTSWORD" + public final void mFTSWORD() throws RecognitionException { + try { + int _type = FTSWORD; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1509:9: ( ( F_ESC | START_WORD ) ( F_ESC | IN_WORD )* ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1510:9: ( F_ESC | START_WORD ) ( F_ESC | IN_WORD )* + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1510:9: ( F_ESC | START_WORD ) + int alt55=2; + int LA55_0 = input.LA(1); + if ( (LA55_0=='\\') ) { + alt55=1; + } + else if ( (LA55_0=='$'||(LA55_0 >= '0' && LA55_0 <= '9')||(LA55_0 >= 'A' && LA55_0 <= 'Z')||(LA55_0 >= 'a' && LA55_0 <= 'z')||(LA55_0 >= '\u00A2' && LA55_0 <= '\u00A7')||(LA55_0 >= '\u00A9' && LA55_0 <= '\u00AA')||LA55_0=='\u00AE'||LA55_0=='\u00B0'||(LA55_0 >= '\u00B2' && LA55_0 <= '\u00B3')||(LA55_0 >= '\u00B5' && LA55_0 <= '\u00B6')||(LA55_0 >= '\u00B9' && LA55_0 <= '\u00BA')||(LA55_0 >= '\u00BC' && LA55_0 <= '\u00BE')||(LA55_0 >= '\u00C0' && LA55_0 <= '\u00D6')||(LA55_0 >= '\u00D8' && LA55_0 <= '\u00F6')||(LA55_0 >= '\u00F8' && LA55_0 <= '\u0236')||(LA55_0 >= '\u0250' && LA55_0 <= '\u02C1')||(LA55_0 >= '\u02C6' && LA55_0 <= '\u02D1')||(LA55_0 >= '\u02E0' && LA55_0 <= '\u02E4')||LA55_0=='\u02EE'||(LA55_0 >= '\u0300' && LA55_0 <= '\u0357')||(LA55_0 >= '\u035D' && LA55_0 <= '\u036F')||LA55_0=='\u037A'||LA55_0=='\u0386'||(LA55_0 >= '\u0388' && LA55_0 <= '\u038A')||LA55_0=='\u038C'||(LA55_0 >= '\u038E' && LA55_0 <= '\u03A1')||(LA55_0 >= '\u03A3' && LA55_0 <= '\u03CE')||(LA55_0 >= '\u03D0' && LA55_0 <= '\u03F5')||(LA55_0 >= '\u03F7' && LA55_0 <= '\u03FB')||(LA55_0 >= '\u0400' && LA55_0 <= '\u0486')||(LA55_0 >= '\u0488' && LA55_0 <= '\u04CE')||(LA55_0 >= '\u04D0' && LA55_0 <= '\u04F5')||(LA55_0 >= '\u04F8' && LA55_0 <= '\u04F9')||(LA55_0 >= '\u0500' && LA55_0 <= '\u050F')||(LA55_0 >= '\u0531' && LA55_0 <= '\u0556')||LA55_0=='\u0559'||(LA55_0 >= '\u0561' && LA55_0 <= '\u0587')||(LA55_0 >= '\u0591' && LA55_0 <= '\u05A1')||(LA55_0 >= '\u05A3' && LA55_0 <= '\u05B9')||(LA55_0 >= '\u05BB' && LA55_0 <= '\u05BD')||LA55_0=='\u05BF'||(LA55_0 >= '\u05C1' && LA55_0 <= '\u05C2')||LA55_0=='\u05C4'||(LA55_0 >= '\u05D0' && LA55_0 <= '\u05EA')||(LA55_0 >= '\u05F0' && LA55_0 <= '\u05F2')||(LA55_0 >= '\u060E' && LA55_0 <= '\u0615')||(LA55_0 >= '\u0621' && LA55_0 <= '\u063A')||(LA55_0 >= '\u0640' && LA55_0 <= '\u0658')||(LA55_0 >= '\u0660' && LA55_0 <= '\u0669')||(LA55_0 >= '\u066E' && LA55_0 <= '\u06D3')||(LA55_0 >= '\u06D5' && LA55_0 <= '\u06DC')||(LA55_0 >= '\u06DE' && LA55_0 <= '\u06FF')||(LA55_0 >= '\u0710' && LA55_0 <= '\u074A')||(LA55_0 >= '\u074D' && LA55_0 <= '\u074F')||(LA55_0 >= '\u0780' && LA55_0 <= '\u07B1')||(LA55_0 >= '\u0901' && LA55_0 <= '\u0939')||(LA55_0 >= '\u093C' && LA55_0 <= '\u094D')||(LA55_0 >= '\u0950' && LA55_0 <= '\u0954')||(LA55_0 >= '\u0958' && LA55_0 <= '\u0963')||(LA55_0 >= '\u0966' && LA55_0 <= '\u096F')||(LA55_0 >= '\u0981' && LA55_0 <= '\u0983')||(LA55_0 >= '\u0985' && LA55_0 <= '\u098C')||(LA55_0 >= '\u098F' && LA55_0 <= '\u0990')||(LA55_0 >= '\u0993' && LA55_0 <= '\u09A8')||(LA55_0 >= '\u09AA' && LA55_0 <= '\u09B0')||LA55_0=='\u09B2'||(LA55_0 >= '\u09B6' && LA55_0 <= '\u09B9')||(LA55_0 >= '\u09BC' && LA55_0 <= '\u09C4')||(LA55_0 >= '\u09C7' && LA55_0 <= '\u09C8')||(LA55_0 >= '\u09CB' && LA55_0 <= '\u09CD')||LA55_0=='\u09D7'||(LA55_0 >= '\u09DC' && LA55_0 <= '\u09DD')||(LA55_0 >= '\u09DF' && LA55_0 <= '\u09E3')||(LA55_0 >= '\u09E6' && LA55_0 <= '\u09FA')||(LA55_0 >= '\u0A01' && LA55_0 <= '\u0A03')||(LA55_0 >= '\u0A05' && LA55_0 <= '\u0A0A')||(LA55_0 >= '\u0A0F' && LA55_0 <= '\u0A10')||(LA55_0 >= '\u0A13' && LA55_0 <= '\u0A28')||(LA55_0 >= '\u0A2A' && LA55_0 <= '\u0A30')||(LA55_0 >= '\u0A32' && LA55_0 <= '\u0A33')||(LA55_0 >= '\u0A35' && LA55_0 <= '\u0A36')||(LA55_0 >= '\u0A38' && LA55_0 <= '\u0A39')||LA55_0=='\u0A3C'||(LA55_0 >= '\u0A3E' && LA55_0 <= '\u0A42')||(LA55_0 >= '\u0A47' && LA55_0 <= '\u0A48')||(LA55_0 >= '\u0A4B' && LA55_0 <= '\u0A4D')||(LA55_0 >= '\u0A59' && LA55_0 <= '\u0A5C')||LA55_0=='\u0A5E'||(LA55_0 >= '\u0A66' && LA55_0 <= '\u0A74')||(LA55_0 >= '\u0A81' && LA55_0 <= '\u0A83')||(LA55_0 >= '\u0A85' && LA55_0 <= '\u0A8D')||(LA55_0 >= '\u0A8F' && LA55_0 <= '\u0A91')||(LA55_0 >= '\u0A93' && LA55_0 <= '\u0AA8')||(LA55_0 >= '\u0AAA' && LA55_0 <= '\u0AB0')||(LA55_0 >= '\u0AB2' && LA55_0 <= '\u0AB3')||(LA55_0 >= '\u0AB5' && LA55_0 <= '\u0AB9')||(LA55_0 >= '\u0ABC' && LA55_0 <= '\u0AC5')||(LA55_0 >= '\u0AC7' && LA55_0 <= '\u0AC9')||(LA55_0 >= '\u0ACB' && LA55_0 <= '\u0ACD')||LA55_0=='\u0AD0'||(LA55_0 >= '\u0AE0' && LA55_0 <= '\u0AE3')||(LA55_0 >= '\u0AE6' && LA55_0 <= '\u0AEF')||LA55_0=='\u0AF1'||(LA55_0 >= '\u0B01' && LA55_0 <= '\u0B03')||(LA55_0 >= '\u0B05' && LA55_0 <= '\u0B0C')||(LA55_0 >= '\u0B0F' && LA55_0 <= '\u0B10')||(LA55_0 >= '\u0B13' && LA55_0 <= '\u0B28')||(LA55_0 >= '\u0B2A' && LA55_0 <= '\u0B30')||(LA55_0 >= '\u0B32' && LA55_0 <= '\u0B33')||(LA55_0 >= '\u0B35' && LA55_0 <= '\u0B39')||(LA55_0 >= '\u0B3C' && LA55_0 <= '\u0B43')||(LA55_0 >= '\u0B47' && LA55_0 <= '\u0B48')||(LA55_0 >= '\u0B4B' && LA55_0 <= '\u0B4D')||(LA55_0 >= '\u0B56' && LA55_0 <= '\u0B57')||(LA55_0 >= '\u0B5C' && LA55_0 <= '\u0B5D')||(LA55_0 >= '\u0B5F' && LA55_0 <= '\u0B61')||(LA55_0 >= '\u0B66' && LA55_0 <= '\u0B71')||(LA55_0 >= '\u0B82' && LA55_0 <= '\u0B83')||(LA55_0 >= '\u0B85' && LA55_0 <= '\u0B8A')||(LA55_0 >= '\u0B8E' && LA55_0 <= '\u0B90')||(LA55_0 >= '\u0B92' && LA55_0 <= '\u0B95')||(LA55_0 >= '\u0B99' && LA55_0 <= '\u0B9A')||LA55_0=='\u0B9C'||(LA55_0 >= '\u0B9E' && LA55_0 <= '\u0B9F')||(LA55_0 >= '\u0BA3' && LA55_0 <= '\u0BA4')||(LA55_0 >= '\u0BA8' && LA55_0 <= '\u0BAA')||(LA55_0 >= '\u0BAE' && LA55_0 <= '\u0BB5')||(LA55_0 >= '\u0BB7' && LA55_0 <= '\u0BB9')||(LA55_0 >= '\u0BBE' && LA55_0 <= '\u0BC2')||(LA55_0 >= '\u0BC6' && LA55_0 <= '\u0BC8')||(LA55_0 >= '\u0BCA' && LA55_0 <= '\u0BCD')||LA55_0=='\u0BD7'||(LA55_0 >= '\u0BE7' && LA55_0 <= '\u0BFA')||(LA55_0 >= '\u0C01' && LA55_0 <= '\u0C03')||(LA55_0 >= '\u0C05' && LA55_0 <= '\u0C0C')||(LA55_0 >= '\u0C0E' && LA55_0 <= '\u0C10')||(LA55_0 >= '\u0C12' && LA55_0 <= '\u0C28')||(LA55_0 >= '\u0C2A' && LA55_0 <= '\u0C33')||(LA55_0 >= '\u0C35' && LA55_0 <= '\u0C39')||(LA55_0 >= '\u0C3E' && LA55_0 <= '\u0C44')||(LA55_0 >= '\u0C46' && LA55_0 <= '\u0C48')||(LA55_0 >= '\u0C4A' && LA55_0 <= '\u0C4D')||(LA55_0 >= '\u0C55' && LA55_0 <= '\u0C56')||(LA55_0 >= '\u0C60' && LA55_0 <= '\u0C61')||(LA55_0 >= '\u0C66' && LA55_0 <= '\u0C6F')||(LA55_0 >= '\u0C82' && LA55_0 <= '\u0C83')||(LA55_0 >= '\u0C85' && LA55_0 <= '\u0C8C')||(LA55_0 >= '\u0C8E' && LA55_0 <= '\u0C90')||(LA55_0 >= '\u0C92' && LA55_0 <= '\u0CA8')||(LA55_0 >= '\u0CAA' && LA55_0 <= '\u0CB3')||(LA55_0 >= '\u0CB5' && LA55_0 <= '\u0CB9')||(LA55_0 >= '\u0CBC' && LA55_0 <= '\u0CC4')||(LA55_0 >= '\u0CC6' && LA55_0 <= '\u0CC8')||(LA55_0 >= '\u0CCA' && LA55_0 <= '\u0CCD')||(LA55_0 >= '\u0CD5' && LA55_0 <= '\u0CD6')||LA55_0=='\u0CDE'||(LA55_0 >= '\u0CE0' && LA55_0 <= '\u0CE1')||(LA55_0 >= '\u0CE6' && LA55_0 <= '\u0CEF')||(LA55_0 >= '\u0D02' && LA55_0 <= '\u0D03')||(LA55_0 >= '\u0D05' && LA55_0 <= '\u0D0C')||(LA55_0 >= '\u0D0E' && LA55_0 <= '\u0D10')||(LA55_0 >= '\u0D12' && LA55_0 <= '\u0D28')||(LA55_0 >= '\u0D2A' && LA55_0 <= '\u0D39')||(LA55_0 >= '\u0D3E' && LA55_0 <= '\u0D43')||(LA55_0 >= '\u0D46' && LA55_0 <= '\u0D48')||(LA55_0 >= '\u0D4A' && LA55_0 <= '\u0D4D')||LA55_0=='\u0D57'||(LA55_0 >= '\u0D60' && LA55_0 <= '\u0D61')||(LA55_0 >= '\u0D66' && LA55_0 <= '\u0D6F')||(LA55_0 >= '\u0D82' && LA55_0 <= '\u0D83')||(LA55_0 >= '\u0D85' && LA55_0 <= '\u0D96')||(LA55_0 >= '\u0D9A' && LA55_0 <= '\u0DB1')||(LA55_0 >= '\u0DB3' && LA55_0 <= '\u0DBB')||LA55_0=='\u0DBD'||(LA55_0 >= '\u0DC0' && LA55_0 <= '\u0DC6')||LA55_0=='\u0DCA'||(LA55_0 >= '\u0DCF' && LA55_0 <= '\u0DD4')||LA55_0=='\u0DD6'||(LA55_0 >= '\u0DD8' && LA55_0 <= '\u0DDF')||(LA55_0 >= '\u0DF2' && LA55_0 <= '\u0DF3')||(LA55_0 >= '\u0E01' && LA55_0 <= '\u0E3A')||(LA55_0 >= '\u0E3F' && LA55_0 <= '\u0E4E')||(LA55_0 >= '\u0E50' && LA55_0 <= '\u0E59')||(LA55_0 >= '\u0E81' && LA55_0 <= '\u0E82')||LA55_0=='\u0E84'||(LA55_0 >= '\u0E87' && LA55_0 <= '\u0E88')||LA55_0=='\u0E8A'||LA55_0=='\u0E8D'||(LA55_0 >= '\u0E94' && LA55_0 <= '\u0E97')||(LA55_0 >= '\u0E99' && LA55_0 <= '\u0E9F')||(LA55_0 >= '\u0EA1' && LA55_0 <= '\u0EA3')||LA55_0=='\u0EA5'||LA55_0=='\u0EA7'||(LA55_0 >= '\u0EAA' && LA55_0 <= '\u0EAB')||(LA55_0 >= '\u0EAD' && LA55_0 <= '\u0EB9')||(LA55_0 >= '\u0EBB' && LA55_0 <= '\u0EBD')||(LA55_0 >= '\u0EC0' && LA55_0 <= '\u0EC4')||LA55_0=='\u0EC6'||(LA55_0 >= '\u0EC8' && LA55_0 <= '\u0ECD')||(LA55_0 >= '\u0ED0' && LA55_0 <= '\u0ED9')||(LA55_0 >= '\u0EDC' && LA55_0 <= '\u0EDD')||(LA55_0 >= '\u0F00' && LA55_0 <= '\u0F03')||(LA55_0 >= '\u0F13' && LA55_0 <= '\u0F39')||(LA55_0 >= '\u0F3E' && LA55_0 <= '\u0F47')||(LA55_0 >= '\u0F49' && LA55_0 <= '\u0F6A')||(LA55_0 >= '\u0F71' && LA55_0 <= '\u0F84')||(LA55_0 >= '\u0F86' && LA55_0 <= '\u0F8B')||(LA55_0 >= '\u0F90' && LA55_0 <= '\u0F97')||(LA55_0 >= '\u0F99' && LA55_0 <= '\u0FBC')||(LA55_0 >= '\u0FBE' && LA55_0 <= '\u0FCC')||LA55_0=='\u0FCF'||(LA55_0 >= '\u1000' && LA55_0 <= '\u1021')||(LA55_0 >= '\u1023' && LA55_0 <= '\u1027')||(LA55_0 >= '\u1029' && LA55_0 <= '\u102A')||(LA55_0 >= '\u102C' && LA55_0 <= '\u1032')||(LA55_0 >= '\u1036' && LA55_0 <= '\u1039')||(LA55_0 >= '\u1040' && LA55_0 <= '\u1049')||(LA55_0 >= '\u1050' && LA55_0 <= '\u1059')||(LA55_0 >= '\u10A0' && LA55_0 <= '\u10C5')||(LA55_0 >= '\u10D0' && LA55_0 <= '\u10F8')||(LA55_0 >= '\u1100' && LA55_0 <= '\u1159')||(LA55_0 >= '\u115F' && LA55_0 <= '\u11A2')||(LA55_0 >= '\u11A8' && LA55_0 <= '\u11F9')||(LA55_0 >= '\u1200' && LA55_0 <= '\u1206')||(LA55_0 >= '\u1208' && LA55_0 <= '\u1246')||LA55_0=='\u1248'||(LA55_0 >= '\u124A' && LA55_0 <= '\u124D')||(LA55_0 >= '\u1250' && LA55_0 <= '\u1256')||LA55_0=='\u1258'||(LA55_0 >= '\u125A' && LA55_0 <= '\u125D')||(LA55_0 >= '\u1260' && LA55_0 <= '\u1286')||LA55_0=='\u1288'||(LA55_0 >= '\u128A' && LA55_0 <= '\u128D')||(LA55_0 >= '\u1290' && LA55_0 <= '\u12AE')||LA55_0=='\u12B0'||(LA55_0 >= '\u12B2' && LA55_0 <= '\u12B5')||(LA55_0 >= '\u12B8' && LA55_0 <= '\u12BE')||LA55_0=='\u12C0'||(LA55_0 >= '\u12C2' && LA55_0 <= '\u12C5')||(LA55_0 >= '\u12C8' && LA55_0 <= '\u12CE')||(LA55_0 >= '\u12D0' && LA55_0 <= '\u12D6')||(LA55_0 >= '\u12D8' && LA55_0 <= '\u12EE')||(LA55_0 >= '\u12F0' && LA55_0 <= '\u130E')||LA55_0=='\u1310'||(LA55_0 >= '\u1312' && LA55_0 <= '\u1315')||(LA55_0 >= '\u1318' && LA55_0 <= '\u131E')||(LA55_0 >= '\u1320' && LA55_0 <= '\u1346')||(LA55_0 >= '\u1348' && LA55_0 <= '\u135A')||(LA55_0 >= '\u1369' && LA55_0 <= '\u137C')||(LA55_0 >= '\u13A0' && LA55_0 <= '\u13F4')||(LA55_0 >= '\u1401' && LA55_0 <= '\u166C')||(LA55_0 >= '\u166F' && LA55_0 <= '\u1676')||(LA55_0 >= '\u1681' && LA55_0 <= '\u169A')||(LA55_0 >= '\u16A0' && LA55_0 <= '\u16EA')||(LA55_0 >= '\u16EE' && LA55_0 <= '\u16F0')||(LA55_0 >= '\u1700' && LA55_0 <= '\u170C')||(LA55_0 >= '\u170E' && LA55_0 <= '\u1714')||(LA55_0 >= '\u1720' && LA55_0 <= '\u1734')||(LA55_0 >= '\u1740' && LA55_0 <= '\u1753')||(LA55_0 >= '\u1760' && LA55_0 <= '\u176C')||(LA55_0 >= '\u176E' && LA55_0 <= '\u1770')||(LA55_0 >= '\u1772' && LA55_0 <= '\u1773')||(LA55_0 >= '\u1780' && LA55_0 <= '\u17B3')||(LA55_0 >= '\u17B6' && LA55_0 <= '\u17D3')||LA55_0=='\u17D7'||(LA55_0 >= '\u17DB' && LA55_0 <= '\u17DD')||(LA55_0 >= '\u17E0' && LA55_0 <= '\u17E9')||(LA55_0 >= '\u17F0' && LA55_0 <= '\u17F9')||(LA55_0 >= '\u180B' && LA55_0 <= '\u180D')||(LA55_0 >= '\u1810' && LA55_0 <= '\u1819')||(LA55_0 >= '\u1820' && LA55_0 <= '\u1877')||(LA55_0 >= '\u1880' && LA55_0 <= '\u18A9')||(LA55_0 >= '\u1900' && LA55_0 <= '\u191C')||(LA55_0 >= '\u1920' && LA55_0 <= '\u192B')||(LA55_0 >= '\u1930' && LA55_0 <= '\u193B')||LA55_0=='\u1940'||(LA55_0 >= '\u1946' && LA55_0 <= '\u196D')||(LA55_0 >= '\u1970' && LA55_0 <= '\u1974')||(LA55_0 >= '\u19E0' && LA55_0 <= '\u19FF')||(LA55_0 >= '\u1D00' && LA55_0 <= '\u1D6B')||(LA55_0 >= '\u1E00' && LA55_0 <= '\u1E9B')||(LA55_0 >= '\u1EA0' && LA55_0 <= '\u1EF9')||(LA55_0 >= '\u1F00' && LA55_0 <= '\u1F15')||(LA55_0 >= '\u1F18' && LA55_0 <= '\u1F1D')||(LA55_0 >= '\u1F20' && LA55_0 <= '\u1F45')||(LA55_0 >= '\u1F48' && LA55_0 <= '\u1F4D')||(LA55_0 >= '\u1F50' && LA55_0 <= '\u1F57')||LA55_0=='\u1F59'||LA55_0=='\u1F5B'||LA55_0=='\u1F5D'||(LA55_0 >= '\u1F5F' && LA55_0 <= '\u1F7D')||(LA55_0 >= '\u1F80' && LA55_0 <= '\u1FB4')||(LA55_0 >= '\u1FB6' && LA55_0 <= '\u1FBC')||LA55_0=='\u1FBE'||(LA55_0 >= '\u1FC2' && LA55_0 <= '\u1FC4')||(LA55_0 >= '\u1FC6' && LA55_0 <= '\u1FCC')||(LA55_0 >= '\u1FD0' && LA55_0 <= '\u1FD3')||(LA55_0 >= '\u1FD6' && LA55_0 <= '\u1FDB')||(LA55_0 >= '\u1FE0' && LA55_0 <= '\u1FEC')||(LA55_0 >= '\u1FF2' && LA55_0 <= '\u1FF4')||(LA55_0 >= '\u1FF6' && LA55_0 <= '\u1FFC')||(LA55_0 >= '\u2070' && LA55_0 <= '\u2071')||(LA55_0 >= '\u2074' && LA55_0 <= '\u2079')||(LA55_0 >= '\u207F' && LA55_0 <= '\u2089')||(LA55_0 >= '\u20A0' && LA55_0 <= '\u20B1')||(LA55_0 >= '\u20D0' && LA55_0 <= '\u20EA')||(LA55_0 >= '\u2100' && LA55_0 <= '\u213B')||(LA55_0 >= '\u213D' && LA55_0 <= '\u213F')||(LA55_0 >= '\u2145' && LA55_0 <= '\u214A')||(LA55_0 >= '\u2153' && LA55_0 <= '\u2183')||(LA55_0 >= '\u2195' && LA55_0 <= '\u2199')||(LA55_0 >= '\u219C' && LA55_0 <= '\u219F')||(LA55_0 >= '\u21A1' && LA55_0 <= '\u21A2')||(LA55_0 >= '\u21A4' && LA55_0 <= '\u21A5')||(LA55_0 >= '\u21A7' && LA55_0 <= '\u21AD')||(LA55_0 >= '\u21AF' && LA55_0 <= '\u21CD')||(LA55_0 >= '\u21D0' && LA55_0 <= '\u21D1')||LA55_0=='\u21D3'||(LA55_0 >= '\u21D5' && LA55_0 <= '\u21F3')||(LA55_0 >= '\u2300' && LA55_0 <= '\u2307')||(LA55_0 >= '\u230C' && LA55_0 <= '\u231F')||(LA55_0 >= '\u2322' && LA55_0 <= '\u2328')||(LA55_0 >= '\u232B' && LA55_0 <= '\u237B')||(LA55_0 >= '\u237D' && LA55_0 <= '\u239A')||(LA55_0 >= '\u23B7' && LA55_0 <= '\u23D0')||(LA55_0 >= '\u2400' && LA55_0 <= '\u2426')||(LA55_0 >= '\u2440' && LA55_0 <= '\u244A')||(LA55_0 >= '\u2460' && LA55_0 <= '\u25B6')||(LA55_0 >= '\u25B8' && LA55_0 <= '\u25C0')||(LA55_0 >= '\u25C2' && LA55_0 <= '\u25F7')||(LA55_0 >= '\u2600' && LA55_0 <= '\u2617')||(LA55_0 >= '\u2619' && LA55_0 <= '\u266E')||(LA55_0 >= '\u2670' && LA55_0 <= '\u267D')||(LA55_0 >= '\u2680' && LA55_0 <= '\u2691')||(LA55_0 >= '\u26A0' && LA55_0 <= '\u26A1')||(LA55_0 >= '\u2701' && LA55_0 <= '\u2704')||(LA55_0 >= '\u2706' && LA55_0 <= '\u2709')||(LA55_0 >= '\u270C' && LA55_0 <= '\u2727')||(LA55_0 >= '\u2729' && LA55_0 <= '\u274B')||LA55_0=='\u274D'||(LA55_0 >= '\u274F' && LA55_0 <= '\u2752')||LA55_0=='\u2756'||(LA55_0 >= '\u2758' && LA55_0 <= '\u275E')||(LA55_0 >= '\u2761' && LA55_0 <= '\u2767')||(LA55_0 >= '\u2776' && LA55_0 <= '\u2794')||(LA55_0 >= '\u2798' && LA55_0 <= '\u27AF')||(LA55_0 >= '\u27B1' && LA55_0 <= '\u27BE')||(LA55_0 >= '\u2800' && LA55_0 <= '\u28FF')||(LA55_0 >= '\u2B00' && LA55_0 <= '\u2B0D')||(LA55_0 >= '\u2E80' && LA55_0 <= '\u2E99')||(LA55_0 >= '\u2E9B' && LA55_0 <= '\u2EF3')||(LA55_0 >= '\u2F00' && LA55_0 <= '\u2FD5')||(LA55_0 >= '\u2FF0' && LA55_0 <= '\u2FFB')||(LA55_0 >= '\u3004' && LA55_0 <= '\u3007')||(LA55_0 >= '\u3012' && LA55_0 <= '\u3013')||(LA55_0 >= '\u3020' && LA55_0 <= '\u302F')||(LA55_0 >= '\u3031' && LA55_0 <= '\u303C')||(LA55_0 >= '\u303E' && LA55_0 <= '\u303F')||(LA55_0 >= '\u3041' && LA55_0 <= '\u3096')||(LA55_0 >= '\u3099' && LA55_0 <= '\u309A')||(LA55_0 >= '\u309D' && LA55_0 <= '\u309F')||(LA55_0 >= '\u30A1' && LA55_0 <= '\u30FA')||(LA55_0 >= '\u30FC' && LA55_0 <= '\u30FF')||(LA55_0 >= '\u3105' && LA55_0 <= '\u312C')||(LA55_0 >= '\u3131' && LA55_0 <= '\u318E')||(LA55_0 >= '\u3190' && LA55_0 <= '\u31B7')||(LA55_0 >= '\u31F0' && LA55_0 <= '\u321E')||(LA55_0 >= '\u3220' && LA55_0 <= '\u3243')||(LA55_0 >= '\u3250' && LA55_0 <= '\u327D')||(LA55_0 >= '\u327F' && LA55_0 <= '\u32FE')||(LA55_0 >= '\u3300' && LA55_0 <= '\u4DB5')||(LA55_0 >= '\u4DC0' && LA55_0 <= '\u9FA5')||(LA55_0 >= '\uA000' && LA55_0 <= '\uA48C')||(LA55_0 >= '\uA490' && LA55_0 <= '\uA4C6')||(LA55_0 >= '\uAC00' && LA55_0 <= '\uD7A3')||(LA55_0 >= '\uF900' && LA55_0 <= '\uFA2D')||(LA55_0 >= '\uFA30' && LA55_0 <= '\uFA6A')||(LA55_0 >= '\uFB00' && LA55_0 <= '\uFB06')||(LA55_0 >= '\uFB13' && LA55_0 <= '\uFB17')||(LA55_0 >= '\uFB1D' && LA55_0 <= '\uFB28')||(LA55_0 >= '\uFB2A' && LA55_0 <= '\uFB36')||(LA55_0 >= '\uFB38' && LA55_0 <= '\uFB3C')||LA55_0=='\uFB3E'||(LA55_0 >= '\uFB40' && LA55_0 <= '\uFB41')||(LA55_0 >= '\uFB43' && LA55_0 <= '\uFB44')||(LA55_0 >= '\uFB46' && LA55_0 <= '\uFBB1')||(LA55_0 >= '\uFBD3' && LA55_0 <= '\uFD3D')||(LA55_0 >= '\uFD50' && LA55_0 <= '\uFD8F')||(LA55_0 >= '\uFD92' && LA55_0 <= '\uFDC7')||(LA55_0 >= '\uFDF0' && LA55_0 <= '\uFDFD')||(LA55_0 >= '\uFE00' && LA55_0 <= '\uFE0F')||(LA55_0 >= '\uFE20' && LA55_0 <= '\uFE23')||LA55_0=='\uFE69'||(LA55_0 >= '\uFE70' && LA55_0 <= '\uFE74')||(LA55_0 >= '\uFE76' && LA55_0 <= '\uFEFC')||LA55_0=='\uFF04'||(LA55_0 >= '\uFF10' && LA55_0 <= '\uFF19')||(LA55_0 >= '\uFF21' && LA55_0 <= '\uFF3A')||(LA55_0 >= '\uFF41' && LA55_0 <= '\uFF5A')||(LA55_0 >= '\uFF66' && LA55_0 <= '\uFFBE')||(LA55_0 >= '\uFFC2' && LA55_0 <= '\uFFC7')||(LA55_0 >= '\uFFCA' && LA55_0 <= '\uFFCF')||(LA55_0 >= '\uFFD2' && LA55_0 <= '\uFFD7')||(LA55_0 >= '\uFFDA' && LA55_0 <= '\uFFDC')||(LA55_0 >= '\uFFE0' && LA55_0 <= '\uFFE1')||(LA55_0 >= '\uFFE4' && LA55_0 <= '\uFFE6')||LA55_0=='\uFFE8'||(LA55_0 >= '\uFFED' && LA55_0 <= '\uFFEE')) ) { + alt55=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + NoViableAltException nvae = + new NoViableAltException("", 55, 0, input); + throw nvae; + } + + switch (alt55) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1511:17: F_ESC + { + mF_ESC(); if (state.failed) return; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1512:19: START_WORD + { + mSTART_WORD(); if (state.failed) return; + + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1514:9: ( F_ESC | IN_WORD )* + loop56: + while (true) { + int alt56=3; + int LA56_0 = input.LA(1); + if ( (LA56_0=='\\') ) { + alt56=1; + } + else if ( ((LA56_0 >= '!' && LA56_0 <= '\'')||LA56_0=='+'||LA56_0=='-'||(LA56_0 >= '/' && LA56_0 <= '9')||LA56_0==';'||LA56_0=='='||(LA56_0 >= '@' && LA56_0 <= 'Z')||LA56_0=='_'||(LA56_0 >= 'a' && LA56_0 <= 'z')||LA56_0=='|'||(LA56_0 >= '\u00A1' && LA56_0 <= '\u00A7')||(LA56_0 >= '\u00A9' && LA56_0 <= '\u00AA')||LA56_0=='\u00AC'||LA56_0=='\u00AE'||(LA56_0 >= '\u00B0' && LA56_0 <= '\u00B3')||(LA56_0 >= '\u00B5' && LA56_0 <= '\u00B7')||(LA56_0 >= '\u00B9' && LA56_0 <= '\u00BA')||(LA56_0 >= '\u00BC' && LA56_0 <= '\u0236')||(LA56_0 >= '\u0250' && LA56_0 <= '\u02C1')||(LA56_0 >= '\u02C6' && LA56_0 <= '\u02D1')||(LA56_0 >= '\u02E0' && LA56_0 <= '\u02E4')||LA56_0=='\u02EE'||(LA56_0 >= '\u0300' && LA56_0 <= '\u0357')||(LA56_0 >= '\u035D' && LA56_0 <= '\u036F')||LA56_0=='\u037A'||LA56_0=='\u037E'||(LA56_0 >= '\u0386' && LA56_0 <= '\u038A')||LA56_0=='\u038C'||(LA56_0 >= '\u038E' && LA56_0 <= '\u03A1')||(LA56_0 >= '\u03A3' && LA56_0 <= '\u03CE')||(LA56_0 >= '\u03D0' && LA56_0 <= '\u03FB')||(LA56_0 >= '\u0400' && LA56_0 <= '\u0486')||(LA56_0 >= '\u0488' && LA56_0 <= '\u04CE')||(LA56_0 >= '\u04D0' && LA56_0 <= '\u04F5')||(LA56_0 >= '\u04F8' && LA56_0 <= '\u04F9')||(LA56_0 >= '\u0500' && LA56_0 <= '\u050F')||(LA56_0 >= '\u0531' && LA56_0 <= '\u0556')||(LA56_0 >= '\u0559' && LA56_0 <= '\u055F')||(LA56_0 >= '\u0561' && LA56_0 <= '\u0587')||(LA56_0 >= '\u0589' && LA56_0 <= '\u058A')||(LA56_0 >= '\u0591' && LA56_0 <= '\u05A1')||(LA56_0 >= '\u05A3' && LA56_0 <= '\u05B9')||(LA56_0 >= '\u05BB' && LA56_0 <= '\u05C4')||(LA56_0 >= '\u05D0' && LA56_0 <= '\u05EA')||(LA56_0 >= '\u05F0' && LA56_0 <= '\u05F4')||(LA56_0 >= '\u060C' && LA56_0 <= '\u0615')||LA56_0=='\u061B'||LA56_0=='\u061F'||(LA56_0 >= '\u0621' && LA56_0 <= '\u063A')||(LA56_0 >= '\u0640' && LA56_0 <= '\u0658')||(LA56_0 >= '\u0660' && LA56_0 <= '\u06DC')||(LA56_0 >= '\u06DE' && LA56_0 <= '\u070D')||(LA56_0 >= '\u0710' && LA56_0 <= '\u074A')||(LA56_0 >= '\u074D' && LA56_0 <= '\u074F')||(LA56_0 >= '\u0780' && LA56_0 <= '\u07B1')||(LA56_0 >= '\u0901' && LA56_0 <= '\u0939')||(LA56_0 >= '\u093C' && LA56_0 <= '\u094D')||(LA56_0 >= '\u0950' && LA56_0 <= '\u0954')||(LA56_0 >= '\u0958' && LA56_0 <= '\u0970')||(LA56_0 >= '\u0981' && LA56_0 <= '\u0983')||(LA56_0 >= '\u0985' && LA56_0 <= '\u098C')||(LA56_0 >= '\u098F' && LA56_0 <= '\u0990')||(LA56_0 >= '\u0993' && LA56_0 <= '\u09A8')||(LA56_0 >= '\u09AA' && LA56_0 <= '\u09B0')||LA56_0=='\u09B2'||(LA56_0 >= '\u09B6' && LA56_0 <= '\u09B9')||(LA56_0 >= '\u09BC' && LA56_0 <= '\u09C4')||(LA56_0 >= '\u09C7' && LA56_0 <= '\u09C8')||(LA56_0 >= '\u09CB' && LA56_0 <= '\u09CD')||LA56_0=='\u09D7'||(LA56_0 >= '\u09DC' && LA56_0 <= '\u09DD')||(LA56_0 >= '\u09DF' && LA56_0 <= '\u09E3')||(LA56_0 >= '\u09E6' && LA56_0 <= '\u09FA')||(LA56_0 >= '\u0A01' && LA56_0 <= '\u0A03')||(LA56_0 >= '\u0A05' && LA56_0 <= '\u0A0A')||(LA56_0 >= '\u0A0F' && LA56_0 <= '\u0A10')||(LA56_0 >= '\u0A13' && LA56_0 <= '\u0A28')||(LA56_0 >= '\u0A2A' && LA56_0 <= '\u0A30')||(LA56_0 >= '\u0A32' && LA56_0 <= '\u0A33')||(LA56_0 >= '\u0A35' && LA56_0 <= '\u0A36')||(LA56_0 >= '\u0A38' && LA56_0 <= '\u0A39')||LA56_0=='\u0A3C'||(LA56_0 >= '\u0A3E' && LA56_0 <= '\u0A42')||(LA56_0 >= '\u0A47' && LA56_0 <= '\u0A48')||(LA56_0 >= '\u0A4B' && LA56_0 <= '\u0A4D')||(LA56_0 >= '\u0A59' && LA56_0 <= '\u0A5C')||LA56_0=='\u0A5E'||(LA56_0 >= '\u0A66' && LA56_0 <= '\u0A74')||(LA56_0 >= '\u0A81' && LA56_0 <= '\u0A83')||(LA56_0 >= '\u0A85' && LA56_0 <= '\u0A8D')||(LA56_0 >= '\u0A8F' && LA56_0 <= '\u0A91')||(LA56_0 >= '\u0A93' && LA56_0 <= '\u0AA8')||(LA56_0 >= '\u0AAA' && LA56_0 <= '\u0AB0')||(LA56_0 >= '\u0AB2' && LA56_0 <= '\u0AB3')||(LA56_0 >= '\u0AB5' && LA56_0 <= '\u0AB9')||(LA56_0 >= '\u0ABC' && LA56_0 <= '\u0AC5')||(LA56_0 >= '\u0AC7' && LA56_0 <= '\u0AC9')||(LA56_0 >= '\u0ACB' && LA56_0 <= '\u0ACD')||LA56_0=='\u0AD0'||(LA56_0 >= '\u0AE0' && LA56_0 <= '\u0AE3')||(LA56_0 >= '\u0AE6' && LA56_0 <= '\u0AEF')||LA56_0=='\u0AF1'||(LA56_0 >= '\u0B01' && LA56_0 <= '\u0B03')||(LA56_0 >= '\u0B05' && LA56_0 <= '\u0B0C')||(LA56_0 >= '\u0B0F' && LA56_0 <= '\u0B10')||(LA56_0 >= '\u0B13' && LA56_0 <= '\u0B28')||(LA56_0 >= '\u0B2A' && LA56_0 <= '\u0B30')||(LA56_0 >= '\u0B32' && LA56_0 <= '\u0B33')||(LA56_0 >= '\u0B35' && LA56_0 <= '\u0B39')||(LA56_0 >= '\u0B3C' && LA56_0 <= '\u0B43')||(LA56_0 >= '\u0B47' && LA56_0 <= '\u0B48')||(LA56_0 >= '\u0B4B' && LA56_0 <= '\u0B4D')||(LA56_0 >= '\u0B56' && LA56_0 <= '\u0B57')||(LA56_0 >= '\u0B5C' && LA56_0 <= '\u0B5D')||(LA56_0 >= '\u0B5F' && LA56_0 <= '\u0B61')||(LA56_0 >= '\u0B66' && LA56_0 <= '\u0B71')||(LA56_0 >= '\u0B82' && LA56_0 <= '\u0B83')||(LA56_0 >= '\u0B85' && LA56_0 <= '\u0B8A')||(LA56_0 >= '\u0B8E' && LA56_0 <= '\u0B90')||(LA56_0 >= '\u0B92' && LA56_0 <= '\u0B95')||(LA56_0 >= '\u0B99' && LA56_0 <= '\u0B9A')||LA56_0=='\u0B9C'||(LA56_0 >= '\u0B9E' && LA56_0 <= '\u0B9F')||(LA56_0 >= '\u0BA3' && LA56_0 <= '\u0BA4')||(LA56_0 >= '\u0BA8' && LA56_0 <= '\u0BAA')||(LA56_0 >= '\u0BAE' && LA56_0 <= '\u0BB5')||(LA56_0 >= '\u0BB7' && LA56_0 <= '\u0BB9')||(LA56_0 >= '\u0BBE' && LA56_0 <= '\u0BC2')||(LA56_0 >= '\u0BC6' && LA56_0 <= '\u0BC8')||(LA56_0 >= '\u0BCA' && LA56_0 <= '\u0BCD')||LA56_0=='\u0BD7'||(LA56_0 >= '\u0BE7' && LA56_0 <= '\u0BFA')||(LA56_0 >= '\u0C01' && LA56_0 <= '\u0C03')||(LA56_0 >= '\u0C05' && LA56_0 <= '\u0C0C')||(LA56_0 >= '\u0C0E' && LA56_0 <= '\u0C10')||(LA56_0 >= '\u0C12' && LA56_0 <= '\u0C28')||(LA56_0 >= '\u0C2A' && LA56_0 <= '\u0C33')||(LA56_0 >= '\u0C35' && LA56_0 <= '\u0C39')||(LA56_0 >= '\u0C3E' && LA56_0 <= '\u0C44')||(LA56_0 >= '\u0C46' && LA56_0 <= '\u0C48')||(LA56_0 >= '\u0C4A' && LA56_0 <= '\u0C4D')||(LA56_0 >= '\u0C55' && LA56_0 <= '\u0C56')||(LA56_0 >= '\u0C60' && LA56_0 <= '\u0C61')||(LA56_0 >= '\u0C66' && LA56_0 <= '\u0C6F')||(LA56_0 >= '\u0C82' && LA56_0 <= '\u0C83')||(LA56_0 >= '\u0C85' && LA56_0 <= '\u0C8C')||(LA56_0 >= '\u0C8E' && LA56_0 <= '\u0C90')||(LA56_0 >= '\u0C92' && LA56_0 <= '\u0CA8')||(LA56_0 >= '\u0CAA' && LA56_0 <= '\u0CB3')||(LA56_0 >= '\u0CB5' && LA56_0 <= '\u0CB9')||(LA56_0 >= '\u0CBC' && LA56_0 <= '\u0CC4')||(LA56_0 >= '\u0CC6' && LA56_0 <= '\u0CC8')||(LA56_0 >= '\u0CCA' && LA56_0 <= '\u0CCD')||(LA56_0 >= '\u0CD5' && LA56_0 <= '\u0CD6')||LA56_0=='\u0CDE'||(LA56_0 >= '\u0CE0' && LA56_0 <= '\u0CE1')||(LA56_0 >= '\u0CE6' && LA56_0 <= '\u0CEF')||(LA56_0 >= '\u0D02' && LA56_0 <= '\u0D03')||(LA56_0 >= '\u0D05' && LA56_0 <= '\u0D0C')||(LA56_0 >= '\u0D0E' && LA56_0 <= '\u0D10')||(LA56_0 >= '\u0D12' && LA56_0 <= '\u0D28')||(LA56_0 >= '\u0D2A' && LA56_0 <= '\u0D39')||(LA56_0 >= '\u0D3E' && LA56_0 <= '\u0D43')||(LA56_0 >= '\u0D46' && LA56_0 <= '\u0D48')||(LA56_0 >= '\u0D4A' && LA56_0 <= '\u0D4D')||LA56_0=='\u0D57'||(LA56_0 >= '\u0D60' && LA56_0 <= '\u0D61')||(LA56_0 >= '\u0D66' && LA56_0 <= '\u0D6F')||(LA56_0 >= '\u0D82' && LA56_0 <= '\u0D83')||(LA56_0 >= '\u0D85' && LA56_0 <= '\u0D96')||(LA56_0 >= '\u0D9A' && LA56_0 <= '\u0DB1')||(LA56_0 >= '\u0DB3' && LA56_0 <= '\u0DBB')||LA56_0=='\u0DBD'||(LA56_0 >= '\u0DC0' && LA56_0 <= '\u0DC6')||LA56_0=='\u0DCA'||(LA56_0 >= '\u0DCF' && LA56_0 <= '\u0DD4')||LA56_0=='\u0DD6'||(LA56_0 >= '\u0DD8' && LA56_0 <= '\u0DDF')||(LA56_0 >= '\u0DF2' && LA56_0 <= '\u0DF4')||(LA56_0 >= '\u0E01' && LA56_0 <= '\u0E3A')||(LA56_0 >= '\u0E3F' && LA56_0 <= '\u0E5B')||(LA56_0 >= '\u0E81' && LA56_0 <= '\u0E82')||LA56_0=='\u0E84'||(LA56_0 >= '\u0E87' && LA56_0 <= '\u0E88')||LA56_0=='\u0E8A'||LA56_0=='\u0E8D'||(LA56_0 >= '\u0E94' && LA56_0 <= '\u0E97')||(LA56_0 >= '\u0E99' && LA56_0 <= '\u0E9F')||(LA56_0 >= '\u0EA1' && LA56_0 <= '\u0EA3')||LA56_0=='\u0EA5'||LA56_0=='\u0EA7'||(LA56_0 >= '\u0EAA' && LA56_0 <= '\u0EAB')||(LA56_0 >= '\u0EAD' && LA56_0 <= '\u0EB9')||(LA56_0 >= '\u0EBB' && LA56_0 <= '\u0EBD')||(LA56_0 >= '\u0EC0' && LA56_0 <= '\u0EC4')||LA56_0=='\u0EC6'||(LA56_0 >= '\u0EC8' && LA56_0 <= '\u0ECD')||(LA56_0 >= '\u0ED0' && LA56_0 <= '\u0ED9')||(LA56_0 >= '\u0EDC' && LA56_0 <= '\u0EDD')||(LA56_0 >= '\u0F00' && LA56_0 <= '\u0F39')||(LA56_0 >= '\u0F3E' && LA56_0 <= '\u0F47')||(LA56_0 >= '\u0F49' && LA56_0 <= '\u0F6A')||(LA56_0 >= '\u0F71' && LA56_0 <= '\u0F8B')||(LA56_0 >= '\u0F90' && LA56_0 <= '\u0F97')||(LA56_0 >= '\u0F99' && LA56_0 <= '\u0FBC')||(LA56_0 >= '\u0FBE' && LA56_0 <= '\u0FCC')||LA56_0=='\u0FCF'||(LA56_0 >= '\u1000' && LA56_0 <= '\u1021')||(LA56_0 >= '\u1023' && LA56_0 <= '\u1027')||(LA56_0 >= '\u1029' && LA56_0 <= '\u102A')||(LA56_0 >= '\u102C' && LA56_0 <= '\u1032')||(LA56_0 >= '\u1036' && LA56_0 <= '\u1039')||(LA56_0 >= '\u1040' && LA56_0 <= '\u1059')||(LA56_0 >= '\u10A0' && LA56_0 <= '\u10C5')||(LA56_0 >= '\u10D0' && LA56_0 <= '\u10F8')||LA56_0=='\u10FB'||(LA56_0 >= '\u1100' && LA56_0 <= '\u1159')||(LA56_0 >= '\u115F' && LA56_0 <= '\u11A2')||(LA56_0 >= '\u11A8' && LA56_0 <= '\u11F9')||(LA56_0 >= '\u1200' && LA56_0 <= '\u1206')||(LA56_0 >= '\u1208' && LA56_0 <= '\u1246')||LA56_0=='\u1248'||(LA56_0 >= '\u124A' && LA56_0 <= '\u124D')||(LA56_0 >= '\u1250' && LA56_0 <= '\u1256')||LA56_0=='\u1258'||(LA56_0 >= '\u125A' && LA56_0 <= '\u125D')||(LA56_0 >= '\u1260' && LA56_0 <= '\u1286')||LA56_0=='\u1288'||(LA56_0 >= '\u128A' && LA56_0 <= '\u128D')||(LA56_0 >= '\u1290' && LA56_0 <= '\u12AE')||LA56_0=='\u12B0'||(LA56_0 >= '\u12B2' && LA56_0 <= '\u12B5')||(LA56_0 >= '\u12B8' && LA56_0 <= '\u12BE')||LA56_0=='\u12C0'||(LA56_0 >= '\u12C2' && LA56_0 <= '\u12C5')||(LA56_0 >= '\u12C8' && LA56_0 <= '\u12CE')||(LA56_0 >= '\u12D0' && LA56_0 <= '\u12D6')||(LA56_0 >= '\u12D8' && LA56_0 <= '\u12EE')||(LA56_0 >= '\u12F0' && LA56_0 <= '\u130E')||LA56_0=='\u1310'||(LA56_0 >= '\u1312' && LA56_0 <= '\u1315')||(LA56_0 >= '\u1318' && LA56_0 <= '\u131E')||(LA56_0 >= '\u1320' && LA56_0 <= '\u1346')||(LA56_0 >= '\u1348' && LA56_0 <= '\u135A')||(LA56_0 >= '\u1361' && LA56_0 <= '\u137C')||(LA56_0 >= '\u13A0' && LA56_0 <= '\u13F4')||(LA56_0 >= '\u1401' && LA56_0 <= '\u1676')||(LA56_0 >= '\u1681' && LA56_0 <= '\u169A')||(LA56_0 >= '\u16A0' && LA56_0 <= '\u16F0')||(LA56_0 >= '\u1700' && LA56_0 <= '\u170C')||(LA56_0 >= '\u170E' && LA56_0 <= '\u1714')||(LA56_0 >= '\u1720' && LA56_0 <= '\u1736')||(LA56_0 >= '\u1740' && LA56_0 <= '\u1753')||(LA56_0 >= '\u1760' && LA56_0 <= '\u176C')||(LA56_0 >= '\u176E' && LA56_0 <= '\u1770')||(LA56_0 >= '\u1772' && LA56_0 <= '\u1773')||(LA56_0 >= '\u1780' && LA56_0 <= '\u17B3')||(LA56_0 >= '\u17B6' && LA56_0 <= '\u17DD')||(LA56_0 >= '\u17E0' && LA56_0 <= '\u17E9')||(LA56_0 >= '\u17F0' && LA56_0 <= '\u17F9')||(LA56_0 >= '\u1800' && LA56_0 <= '\u180D')||(LA56_0 >= '\u1810' && LA56_0 <= '\u1819')||(LA56_0 >= '\u1820' && LA56_0 <= '\u1877')||(LA56_0 >= '\u1880' && LA56_0 <= '\u18A9')||(LA56_0 >= '\u1900' && LA56_0 <= '\u191C')||(LA56_0 >= '\u1920' && LA56_0 <= '\u192B')||(LA56_0 >= '\u1930' && LA56_0 <= '\u193B')||LA56_0=='\u1940'||(LA56_0 >= '\u1944' && LA56_0 <= '\u196D')||(LA56_0 >= '\u1970' && LA56_0 <= '\u1974')||(LA56_0 >= '\u19E0' && LA56_0 <= '\u19FF')||(LA56_0 >= '\u1D00' && LA56_0 <= '\u1D6B')||(LA56_0 >= '\u1E00' && LA56_0 <= '\u1E9B')||(LA56_0 >= '\u1EA0' && LA56_0 <= '\u1EF9')||(LA56_0 >= '\u1F00' && LA56_0 <= '\u1F15')||(LA56_0 >= '\u1F18' && LA56_0 <= '\u1F1D')||(LA56_0 >= '\u1F20' && LA56_0 <= '\u1F45')||(LA56_0 >= '\u1F48' && LA56_0 <= '\u1F4D')||(LA56_0 >= '\u1F50' && LA56_0 <= '\u1F57')||LA56_0=='\u1F59'||LA56_0=='\u1F5B'||LA56_0=='\u1F5D'||(LA56_0 >= '\u1F5F' && LA56_0 <= '\u1F7D')||(LA56_0 >= '\u1F80' && LA56_0 <= '\u1FB4')||(LA56_0 >= '\u1FB6' && LA56_0 <= '\u1FBC')||LA56_0=='\u1FBE'||(LA56_0 >= '\u1FC2' && LA56_0 <= '\u1FC4')||(LA56_0 >= '\u1FC6' && LA56_0 <= '\u1FCC')||(LA56_0 >= '\u1FD0' && LA56_0 <= '\u1FD3')||(LA56_0 >= '\u1FD6' && LA56_0 <= '\u1FDB')||(LA56_0 >= '\u1FE0' && LA56_0 <= '\u1FEC')||(LA56_0 >= '\u1FF2' && LA56_0 <= '\u1FF4')||(LA56_0 >= '\u1FF6' && LA56_0 <= '\u1FFC')||(LA56_0 >= '\u2010' && LA56_0 <= '\u2017')||(LA56_0 >= '\u2020' && LA56_0 <= '\u2027')||(LA56_0 >= '\u2030' && LA56_0 <= '\u2038')||(LA56_0 >= '\u203B' && LA56_0 <= '\u2044')||(LA56_0 >= '\u2047' && LA56_0 <= '\u2054')||LA56_0=='\u2057'||(LA56_0 >= '\u2070' && LA56_0 <= '\u2071')||(LA56_0 >= '\u2074' && LA56_0 <= '\u207C')||(LA56_0 >= '\u207F' && LA56_0 <= '\u208C')||(LA56_0 >= '\u20A0' && LA56_0 <= '\u20B1')||(LA56_0 >= '\u20D0' && LA56_0 <= '\u20EA')||(LA56_0 >= '\u2100' && LA56_0 <= '\u213B')||(LA56_0 >= '\u213D' && LA56_0 <= '\u214B')||(LA56_0 >= '\u2153' && LA56_0 <= '\u2183')||(LA56_0 >= '\u2190' && LA56_0 <= '\u2328')||(LA56_0 >= '\u232B' && LA56_0 <= '\u23B3')||(LA56_0 >= '\u23B6' && LA56_0 <= '\u23D0')||(LA56_0 >= '\u2400' && LA56_0 <= '\u2426')||(LA56_0 >= '\u2440' && LA56_0 <= '\u244A')||(LA56_0 >= '\u2460' && LA56_0 <= '\u2617')||(LA56_0 >= '\u2619' && LA56_0 <= '\u267D')||(LA56_0 >= '\u2680' && LA56_0 <= '\u2691')||(LA56_0 >= '\u26A0' && LA56_0 <= '\u26A1')||(LA56_0 >= '\u2701' && LA56_0 <= '\u2704')||(LA56_0 >= '\u2706' && LA56_0 <= '\u2709')||(LA56_0 >= '\u270C' && LA56_0 <= '\u2727')||(LA56_0 >= '\u2729' && LA56_0 <= '\u274B')||LA56_0=='\u274D'||(LA56_0 >= '\u274F' && LA56_0 <= '\u2752')||LA56_0=='\u2756'||(LA56_0 >= '\u2758' && LA56_0 <= '\u275E')||(LA56_0 >= '\u2761' && LA56_0 <= '\u2767')||(LA56_0 >= '\u2776' && LA56_0 <= '\u2794')||(LA56_0 >= '\u2798' && LA56_0 <= '\u27AF')||(LA56_0 >= '\u27B1' && LA56_0 <= '\u27BE')||(LA56_0 >= '\u27D0' && LA56_0 <= '\u27E5')||(LA56_0 >= '\u27F0' && LA56_0 <= '\u2982')||(LA56_0 >= '\u2999' && LA56_0 <= '\u29D7')||(LA56_0 >= '\u29DC' && LA56_0 <= '\u29FB')||(LA56_0 >= '\u29FE' && LA56_0 <= '\u2B0D')||(LA56_0 >= '\u2E80' && LA56_0 <= '\u2E99')||(LA56_0 >= '\u2E9B' && LA56_0 <= '\u2EF3')||(LA56_0 >= '\u2F00' && LA56_0 <= '\u2FD5')||(LA56_0 >= '\u2FF0' && LA56_0 <= '\u2FFB')||(LA56_0 >= '\u3001' && LA56_0 <= '\u3007')||(LA56_0 >= '\u3012' && LA56_0 <= '\u3013')||LA56_0=='\u301C'||(LA56_0 >= '\u3020' && LA56_0 <= '\u303F')||(LA56_0 >= '\u3041' && LA56_0 <= '\u3096')||(LA56_0 >= '\u3099' && LA56_0 <= '\u309A')||(LA56_0 >= '\u309D' && LA56_0 <= '\u30FF')||(LA56_0 >= '\u3105' && LA56_0 <= '\u312C')||(LA56_0 >= '\u3131' && LA56_0 <= '\u318E')||(LA56_0 >= '\u3190' && LA56_0 <= '\u31B7')||(LA56_0 >= '\u31F0' && LA56_0 <= '\u321E')||(LA56_0 >= '\u3220' && LA56_0 <= '\u3243')||(LA56_0 >= '\u3250' && LA56_0 <= '\u327D')||(LA56_0 >= '\u327F' && LA56_0 <= '\u32FE')||(LA56_0 >= '\u3300' && LA56_0 <= '\u4DB5')||(LA56_0 >= '\u4DC0' && LA56_0 <= '\u9FA5')||(LA56_0 >= '\uA000' && LA56_0 <= '\uA48C')||(LA56_0 >= '\uA490' && LA56_0 <= '\uA4C6')||(LA56_0 >= '\uAC00' && LA56_0 <= '\uD7A3')||(LA56_0 >= '\uF900' && LA56_0 <= '\uFA2D')||(LA56_0 >= '\uFA30' && LA56_0 <= '\uFA6A')||(LA56_0 >= '\uFB00' && LA56_0 <= '\uFB06')||(LA56_0 >= '\uFB13' && LA56_0 <= '\uFB17')||(LA56_0 >= '\uFB1D' && LA56_0 <= '\uFB36')||(LA56_0 >= '\uFB38' && LA56_0 <= '\uFB3C')||LA56_0=='\uFB3E'||(LA56_0 >= '\uFB40' && LA56_0 <= '\uFB41')||(LA56_0 >= '\uFB43' && LA56_0 <= '\uFB44')||(LA56_0 >= '\uFB46' && LA56_0 <= '\uFBB1')||(LA56_0 >= '\uFBD3' && LA56_0 <= '\uFD3D')||(LA56_0 >= '\uFD50' && LA56_0 <= '\uFD8F')||(LA56_0 >= '\uFD92' && LA56_0 <= '\uFDC7')||(LA56_0 >= '\uFDF0' && LA56_0 <= '\uFDFD')||(LA56_0 >= '\uFE00' && LA56_0 <= '\uFE0F')||(LA56_0 >= '\uFE20' && LA56_0 <= '\uFE23')||(LA56_0 >= '\uFE30' && LA56_0 <= '\uFE34')||(LA56_0 >= '\uFE45' && LA56_0 <= '\uFE46')||(LA56_0 >= '\uFE49' && LA56_0 <= '\uFE52')||(LA56_0 >= '\uFE54' && LA56_0 <= '\uFE58')||(LA56_0 >= '\uFE5F' && LA56_0 <= '\uFE66')||(LA56_0 >= '\uFE68' && LA56_0 <= '\uFE6B')||(LA56_0 >= '\uFE70' && LA56_0 <= '\uFE74')||(LA56_0 >= '\uFE76' && LA56_0 <= '\uFEFC')||(LA56_0 >= '\uFF01' && LA56_0 <= '\uFF07')||(LA56_0 >= '\uFF0A' && LA56_0 <= '\uFF3A')||LA56_0=='\uFF3C'||LA56_0=='\uFF3F'||(LA56_0 >= '\uFF41' && LA56_0 <= '\uFF5A')||LA56_0=='\uFF5C'||LA56_0=='\uFF5E'||LA56_0=='\uFF61'||(LA56_0 >= '\uFF64' && LA56_0 <= '\uFFBE')||(LA56_0 >= '\uFFC2' && LA56_0 <= '\uFFC7')||(LA56_0 >= '\uFFCA' && LA56_0 <= '\uFFCF')||(LA56_0 >= '\uFFD2' && LA56_0 <= '\uFFD7')||(LA56_0 >= '\uFFDA' && LA56_0 <= '\uFFDC')||(LA56_0 >= '\uFFE0' && LA56_0 <= '\uFFE2')||(LA56_0 >= '\uFFE4' && LA56_0 <= '\uFFE6')||(LA56_0 >= '\uFFE8' && LA56_0 <= '\uFFEE')) ) { + alt56=2; + } + + switch (alt56) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1515:17: F_ESC + { + mF_ESC(); if (state.failed) return; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1516:19: IN_WORD + { + mIN_WORD(); if (state.failed) return; + + } + break; + + default : + break loop56; + } + } + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "FTSWORD" + + // $ANTLR start "FTSPRE" + public final void mFTSPRE() throws RecognitionException { + try { + int _type = FTSPRE; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1521:9: ( ( F_ESC | START_WORD ) ( F_ESC | IN_WORD )* STAR ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1522:9: ( F_ESC | START_WORD ) ( F_ESC | IN_WORD )* STAR + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1522:9: ( F_ESC | START_WORD ) + int alt57=2; + int LA57_0 = input.LA(1); + if ( (LA57_0=='\\') ) { + alt57=1; + } + else if ( (LA57_0=='$'||(LA57_0 >= '0' && LA57_0 <= '9')||(LA57_0 >= 'A' && LA57_0 <= 'Z')||(LA57_0 >= 'a' && LA57_0 <= 'z')||(LA57_0 >= '\u00A2' && LA57_0 <= '\u00A7')||(LA57_0 >= '\u00A9' && LA57_0 <= '\u00AA')||LA57_0=='\u00AE'||LA57_0=='\u00B0'||(LA57_0 >= '\u00B2' && LA57_0 <= '\u00B3')||(LA57_0 >= '\u00B5' && LA57_0 <= '\u00B6')||(LA57_0 >= '\u00B9' && LA57_0 <= '\u00BA')||(LA57_0 >= '\u00BC' && LA57_0 <= '\u00BE')||(LA57_0 >= '\u00C0' && LA57_0 <= '\u00D6')||(LA57_0 >= '\u00D8' && LA57_0 <= '\u00F6')||(LA57_0 >= '\u00F8' && LA57_0 <= '\u0236')||(LA57_0 >= '\u0250' && LA57_0 <= '\u02C1')||(LA57_0 >= '\u02C6' && LA57_0 <= '\u02D1')||(LA57_0 >= '\u02E0' && LA57_0 <= '\u02E4')||LA57_0=='\u02EE'||(LA57_0 >= '\u0300' && LA57_0 <= '\u0357')||(LA57_0 >= '\u035D' && LA57_0 <= '\u036F')||LA57_0=='\u037A'||LA57_0=='\u0386'||(LA57_0 >= '\u0388' && LA57_0 <= '\u038A')||LA57_0=='\u038C'||(LA57_0 >= '\u038E' && LA57_0 <= '\u03A1')||(LA57_0 >= '\u03A3' && LA57_0 <= '\u03CE')||(LA57_0 >= '\u03D0' && LA57_0 <= '\u03F5')||(LA57_0 >= '\u03F7' && LA57_0 <= '\u03FB')||(LA57_0 >= '\u0400' && LA57_0 <= '\u0486')||(LA57_0 >= '\u0488' && LA57_0 <= '\u04CE')||(LA57_0 >= '\u04D0' && LA57_0 <= '\u04F5')||(LA57_0 >= '\u04F8' && LA57_0 <= '\u04F9')||(LA57_0 >= '\u0500' && LA57_0 <= '\u050F')||(LA57_0 >= '\u0531' && LA57_0 <= '\u0556')||LA57_0=='\u0559'||(LA57_0 >= '\u0561' && LA57_0 <= '\u0587')||(LA57_0 >= '\u0591' && LA57_0 <= '\u05A1')||(LA57_0 >= '\u05A3' && LA57_0 <= '\u05B9')||(LA57_0 >= '\u05BB' && LA57_0 <= '\u05BD')||LA57_0=='\u05BF'||(LA57_0 >= '\u05C1' && LA57_0 <= '\u05C2')||LA57_0=='\u05C4'||(LA57_0 >= '\u05D0' && LA57_0 <= '\u05EA')||(LA57_0 >= '\u05F0' && LA57_0 <= '\u05F2')||(LA57_0 >= '\u060E' && LA57_0 <= '\u0615')||(LA57_0 >= '\u0621' && LA57_0 <= '\u063A')||(LA57_0 >= '\u0640' && LA57_0 <= '\u0658')||(LA57_0 >= '\u0660' && LA57_0 <= '\u0669')||(LA57_0 >= '\u066E' && LA57_0 <= '\u06D3')||(LA57_0 >= '\u06D5' && LA57_0 <= '\u06DC')||(LA57_0 >= '\u06DE' && LA57_0 <= '\u06FF')||(LA57_0 >= '\u0710' && LA57_0 <= '\u074A')||(LA57_0 >= '\u074D' && LA57_0 <= '\u074F')||(LA57_0 >= '\u0780' && LA57_0 <= '\u07B1')||(LA57_0 >= '\u0901' && LA57_0 <= '\u0939')||(LA57_0 >= '\u093C' && LA57_0 <= '\u094D')||(LA57_0 >= '\u0950' && LA57_0 <= '\u0954')||(LA57_0 >= '\u0958' && LA57_0 <= '\u0963')||(LA57_0 >= '\u0966' && LA57_0 <= '\u096F')||(LA57_0 >= '\u0981' && LA57_0 <= '\u0983')||(LA57_0 >= '\u0985' && LA57_0 <= '\u098C')||(LA57_0 >= '\u098F' && LA57_0 <= '\u0990')||(LA57_0 >= '\u0993' && LA57_0 <= '\u09A8')||(LA57_0 >= '\u09AA' && LA57_0 <= '\u09B0')||LA57_0=='\u09B2'||(LA57_0 >= '\u09B6' && LA57_0 <= '\u09B9')||(LA57_0 >= '\u09BC' && LA57_0 <= '\u09C4')||(LA57_0 >= '\u09C7' && LA57_0 <= '\u09C8')||(LA57_0 >= '\u09CB' && LA57_0 <= '\u09CD')||LA57_0=='\u09D7'||(LA57_0 >= '\u09DC' && LA57_0 <= '\u09DD')||(LA57_0 >= '\u09DF' && LA57_0 <= '\u09E3')||(LA57_0 >= '\u09E6' && LA57_0 <= '\u09FA')||(LA57_0 >= '\u0A01' && LA57_0 <= '\u0A03')||(LA57_0 >= '\u0A05' && LA57_0 <= '\u0A0A')||(LA57_0 >= '\u0A0F' && LA57_0 <= '\u0A10')||(LA57_0 >= '\u0A13' && LA57_0 <= '\u0A28')||(LA57_0 >= '\u0A2A' && LA57_0 <= '\u0A30')||(LA57_0 >= '\u0A32' && LA57_0 <= '\u0A33')||(LA57_0 >= '\u0A35' && LA57_0 <= '\u0A36')||(LA57_0 >= '\u0A38' && LA57_0 <= '\u0A39')||LA57_0=='\u0A3C'||(LA57_0 >= '\u0A3E' && LA57_0 <= '\u0A42')||(LA57_0 >= '\u0A47' && LA57_0 <= '\u0A48')||(LA57_0 >= '\u0A4B' && LA57_0 <= '\u0A4D')||(LA57_0 >= '\u0A59' && LA57_0 <= '\u0A5C')||LA57_0=='\u0A5E'||(LA57_0 >= '\u0A66' && LA57_0 <= '\u0A74')||(LA57_0 >= '\u0A81' && LA57_0 <= '\u0A83')||(LA57_0 >= '\u0A85' && LA57_0 <= '\u0A8D')||(LA57_0 >= '\u0A8F' && LA57_0 <= '\u0A91')||(LA57_0 >= '\u0A93' && LA57_0 <= '\u0AA8')||(LA57_0 >= '\u0AAA' && LA57_0 <= '\u0AB0')||(LA57_0 >= '\u0AB2' && LA57_0 <= '\u0AB3')||(LA57_0 >= '\u0AB5' && LA57_0 <= '\u0AB9')||(LA57_0 >= '\u0ABC' && LA57_0 <= '\u0AC5')||(LA57_0 >= '\u0AC7' && LA57_0 <= '\u0AC9')||(LA57_0 >= '\u0ACB' && LA57_0 <= '\u0ACD')||LA57_0=='\u0AD0'||(LA57_0 >= '\u0AE0' && LA57_0 <= '\u0AE3')||(LA57_0 >= '\u0AE6' && LA57_0 <= '\u0AEF')||LA57_0=='\u0AF1'||(LA57_0 >= '\u0B01' && LA57_0 <= '\u0B03')||(LA57_0 >= '\u0B05' && LA57_0 <= '\u0B0C')||(LA57_0 >= '\u0B0F' && LA57_0 <= '\u0B10')||(LA57_0 >= '\u0B13' && LA57_0 <= '\u0B28')||(LA57_0 >= '\u0B2A' && LA57_0 <= '\u0B30')||(LA57_0 >= '\u0B32' && LA57_0 <= '\u0B33')||(LA57_0 >= '\u0B35' && LA57_0 <= '\u0B39')||(LA57_0 >= '\u0B3C' && LA57_0 <= '\u0B43')||(LA57_0 >= '\u0B47' && LA57_0 <= '\u0B48')||(LA57_0 >= '\u0B4B' && LA57_0 <= '\u0B4D')||(LA57_0 >= '\u0B56' && LA57_0 <= '\u0B57')||(LA57_0 >= '\u0B5C' && LA57_0 <= '\u0B5D')||(LA57_0 >= '\u0B5F' && LA57_0 <= '\u0B61')||(LA57_0 >= '\u0B66' && LA57_0 <= '\u0B71')||(LA57_0 >= '\u0B82' && LA57_0 <= '\u0B83')||(LA57_0 >= '\u0B85' && LA57_0 <= '\u0B8A')||(LA57_0 >= '\u0B8E' && LA57_0 <= '\u0B90')||(LA57_0 >= '\u0B92' && LA57_0 <= '\u0B95')||(LA57_0 >= '\u0B99' && LA57_0 <= '\u0B9A')||LA57_0=='\u0B9C'||(LA57_0 >= '\u0B9E' && LA57_0 <= '\u0B9F')||(LA57_0 >= '\u0BA3' && LA57_0 <= '\u0BA4')||(LA57_0 >= '\u0BA8' && LA57_0 <= '\u0BAA')||(LA57_0 >= '\u0BAE' && LA57_0 <= '\u0BB5')||(LA57_0 >= '\u0BB7' && LA57_0 <= '\u0BB9')||(LA57_0 >= '\u0BBE' && LA57_0 <= '\u0BC2')||(LA57_0 >= '\u0BC6' && LA57_0 <= '\u0BC8')||(LA57_0 >= '\u0BCA' && LA57_0 <= '\u0BCD')||LA57_0=='\u0BD7'||(LA57_0 >= '\u0BE7' && LA57_0 <= '\u0BFA')||(LA57_0 >= '\u0C01' && LA57_0 <= '\u0C03')||(LA57_0 >= '\u0C05' && LA57_0 <= '\u0C0C')||(LA57_0 >= '\u0C0E' && LA57_0 <= '\u0C10')||(LA57_0 >= '\u0C12' && LA57_0 <= '\u0C28')||(LA57_0 >= '\u0C2A' && LA57_0 <= '\u0C33')||(LA57_0 >= '\u0C35' && LA57_0 <= '\u0C39')||(LA57_0 >= '\u0C3E' && LA57_0 <= '\u0C44')||(LA57_0 >= '\u0C46' && LA57_0 <= '\u0C48')||(LA57_0 >= '\u0C4A' && LA57_0 <= '\u0C4D')||(LA57_0 >= '\u0C55' && LA57_0 <= '\u0C56')||(LA57_0 >= '\u0C60' && LA57_0 <= '\u0C61')||(LA57_0 >= '\u0C66' && LA57_0 <= '\u0C6F')||(LA57_0 >= '\u0C82' && LA57_0 <= '\u0C83')||(LA57_0 >= '\u0C85' && LA57_0 <= '\u0C8C')||(LA57_0 >= '\u0C8E' && LA57_0 <= '\u0C90')||(LA57_0 >= '\u0C92' && LA57_0 <= '\u0CA8')||(LA57_0 >= '\u0CAA' && LA57_0 <= '\u0CB3')||(LA57_0 >= '\u0CB5' && LA57_0 <= '\u0CB9')||(LA57_0 >= '\u0CBC' && LA57_0 <= '\u0CC4')||(LA57_0 >= '\u0CC6' && LA57_0 <= '\u0CC8')||(LA57_0 >= '\u0CCA' && LA57_0 <= '\u0CCD')||(LA57_0 >= '\u0CD5' && LA57_0 <= '\u0CD6')||LA57_0=='\u0CDE'||(LA57_0 >= '\u0CE0' && LA57_0 <= '\u0CE1')||(LA57_0 >= '\u0CE6' && LA57_0 <= '\u0CEF')||(LA57_0 >= '\u0D02' && LA57_0 <= '\u0D03')||(LA57_0 >= '\u0D05' && LA57_0 <= '\u0D0C')||(LA57_0 >= '\u0D0E' && LA57_0 <= '\u0D10')||(LA57_0 >= '\u0D12' && LA57_0 <= '\u0D28')||(LA57_0 >= '\u0D2A' && LA57_0 <= '\u0D39')||(LA57_0 >= '\u0D3E' && LA57_0 <= '\u0D43')||(LA57_0 >= '\u0D46' && LA57_0 <= '\u0D48')||(LA57_0 >= '\u0D4A' && LA57_0 <= '\u0D4D')||LA57_0=='\u0D57'||(LA57_0 >= '\u0D60' && LA57_0 <= '\u0D61')||(LA57_0 >= '\u0D66' && LA57_0 <= '\u0D6F')||(LA57_0 >= '\u0D82' && LA57_0 <= '\u0D83')||(LA57_0 >= '\u0D85' && LA57_0 <= '\u0D96')||(LA57_0 >= '\u0D9A' && LA57_0 <= '\u0DB1')||(LA57_0 >= '\u0DB3' && LA57_0 <= '\u0DBB')||LA57_0=='\u0DBD'||(LA57_0 >= '\u0DC0' && LA57_0 <= '\u0DC6')||LA57_0=='\u0DCA'||(LA57_0 >= '\u0DCF' && LA57_0 <= '\u0DD4')||LA57_0=='\u0DD6'||(LA57_0 >= '\u0DD8' && LA57_0 <= '\u0DDF')||(LA57_0 >= '\u0DF2' && LA57_0 <= '\u0DF3')||(LA57_0 >= '\u0E01' && LA57_0 <= '\u0E3A')||(LA57_0 >= '\u0E3F' && LA57_0 <= '\u0E4E')||(LA57_0 >= '\u0E50' && LA57_0 <= '\u0E59')||(LA57_0 >= '\u0E81' && LA57_0 <= '\u0E82')||LA57_0=='\u0E84'||(LA57_0 >= '\u0E87' && LA57_0 <= '\u0E88')||LA57_0=='\u0E8A'||LA57_0=='\u0E8D'||(LA57_0 >= '\u0E94' && LA57_0 <= '\u0E97')||(LA57_0 >= '\u0E99' && LA57_0 <= '\u0E9F')||(LA57_0 >= '\u0EA1' && LA57_0 <= '\u0EA3')||LA57_0=='\u0EA5'||LA57_0=='\u0EA7'||(LA57_0 >= '\u0EAA' && LA57_0 <= '\u0EAB')||(LA57_0 >= '\u0EAD' && LA57_0 <= '\u0EB9')||(LA57_0 >= '\u0EBB' && LA57_0 <= '\u0EBD')||(LA57_0 >= '\u0EC0' && LA57_0 <= '\u0EC4')||LA57_0=='\u0EC6'||(LA57_0 >= '\u0EC8' && LA57_0 <= '\u0ECD')||(LA57_0 >= '\u0ED0' && LA57_0 <= '\u0ED9')||(LA57_0 >= '\u0EDC' && LA57_0 <= '\u0EDD')||(LA57_0 >= '\u0F00' && LA57_0 <= '\u0F03')||(LA57_0 >= '\u0F13' && LA57_0 <= '\u0F39')||(LA57_0 >= '\u0F3E' && LA57_0 <= '\u0F47')||(LA57_0 >= '\u0F49' && LA57_0 <= '\u0F6A')||(LA57_0 >= '\u0F71' && LA57_0 <= '\u0F84')||(LA57_0 >= '\u0F86' && LA57_0 <= '\u0F8B')||(LA57_0 >= '\u0F90' && LA57_0 <= '\u0F97')||(LA57_0 >= '\u0F99' && LA57_0 <= '\u0FBC')||(LA57_0 >= '\u0FBE' && LA57_0 <= '\u0FCC')||LA57_0=='\u0FCF'||(LA57_0 >= '\u1000' && LA57_0 <= '\u1021')||(LA57_0 >= '\u1023' && LA57_0 <= '\u1027')||(LA57_0 >= '\u1029' && LA57_0 <= '\u102A')||(LA57_0 >= '\u102C' && LA57_0 <= '\u1032')||(LA57_0 >= '\u1036' && LA57_0 <= '\u1039')||(LA57_0 >= '\u1040' && LA57_0 <= '\u1049')||(LA57_0 >= '\u1050' && LA57_0 <= '\u1059')||(LA57_0 >= '\u10A0' && LA57_0 <= '\u10C5')||(LA57_0 >= '\u10D0' && LA57_0 <= '\u10F8')||(LA57_0 >= '\u1100' && LA57_0 <= '\u1159')||(LA57_0 >= '\u115F' && LA57_0 <= '\u11A2')||(LA57_0 >= '\u11A8' && LA57_0 <= '\u11F9')||(LA57_0 >= '\u1200' && LA57_0 <= '\u1206')||(LA57_0 >= '\u1208' && LA57_0 <= '\u1246')||LA57_0=='\u1248'||(LA57_0 >= '\u124A' && LA57_0 <= '\u124D')||(LA57_0 >= '\u1250' && LA57_0 <= '\u1256')||LA57_0=='\u1258'||(LA57_0 >= '\u125A' && LA57_0 <= '\u125D')||(LA57_0 >= '\u1260' && LA57_0 <= '\u1286')||LA57_0=='\u1288'||(LA57_0 >= '\u128A' && LA57_0 <= '\u128D')||(LA57_0 >= '\u1290' && LA57_0 <= '\u12AE')||LA57_0=='\u12B0'||(LA57_0 >= '\u12B2' && LA57_0 <= '\u12B5')||(LA57_0 >= '\u12B8' && LA57_0 <= '\u12BE')||LA57_0=='\u12C0'||(LA57_0 >= '\u12C2' && LA57_0 <= '\u12C5')||(LA57_0 >= '\u12C8' && LA57_0 <= '\u12CE')||(LA57_0 >= '\u12D0' && LA57_0 <= '\u12D6')||(LA57_0 >= '\u12D8' && LA57_0 <= '\u12EE')||(LA57_0 >= '\u12F0' && LA57_0 <= '\u130E')||LA57_0=='\u1310'||(LA57_0 >= '\u1312' && LA57_0 <= '\u1315')||(LA57_0 >= '\u1318' && LA57_0 <= '\u131E')||(LA57_0 >= '\u1320' && LA57_0 <= '\u1346')||(LA57_0 >= '\u1348' && LA57_0 <= '\u135A')||(LA57_0 >= '\u1369' && LA57_0 <= '\u137C')||(LA57_0 >= '\u13A0' && LA57_0 <= '\u13F4')||(LA57_0 >= '\u1401' && LA57_0 <= '\u166C')||(LA57_0 >= '\u166F' && LA57_0 <= '\u1676')||(LA57_0 >= '\u1681' && LA57_0 <= '\u169A')||(LA57_0 >= '\u16A0' && LA57_0 <= '\u16EA')||(LA57_0 >= '\u16EE' && LA57_0 <= '\u16F0')||(LA57_0 >= '\u1700' && LA57_0 <= '\u170C')||(LA57_0 >= '\u170E' && LA57_0 <= '\u1714')||(LA57_0 >= '\u1720' && LA57_0 <= '\u1734')||(LA57_0 >= '\u1740' && LA57_0 <= '\u1753')||(LA57_0 >= '\u1760' && LA57_0 <= '\u176C')||(LA57_0 >= '\u176E' && LA57_0 <= '\u1770')||(LA57_0 >= '\u1772' && LA57_0 <= '\u1773')||(LA57_0 >= '\u1780' && LA57_0 <= '\u17B3')||(LA57_0 >= '\u17B6' && LA57_0 <= '\u17D3')||LA57_0=='\u17D7'||(LA57_0 >= '\u17DB' && LA57_0 <= '\u17DD')||(LA57_0 >= '\u17E0' && LA57_0 <= '\u17E9')||(LA57_0 >= '\u17F0' && LA57_0 <= '\u17F9')||(LA57_0 >= '\u180B' && LA57_0 <= '\u180D')||(LA57_0 >= '\u1810' && LA57_0 <= '\u1819')||(LA57_0 >= '\u1820' && LA57_0 <= '\u1877')||(LA57_0 >= '\u1880' && LA57_0 <= '\u18A9')||(LA57_0 >= '\u1900' && LA57_0 <= '\u191C')||(LA57_0 >= '\u1920' && LA57_0 <= '\u192B')||(LA57_0 >= '\u1930' && LA57_0 <= '\u193B')||LA57_0=='\u1940'||(LA57_0 >= '\u1946' && LA57_0 <= '\u196D')||(LA57_0 >= '\u1970' && LA57_0 <= '\u1974')||(LA57_0 >= '\u19E0' && LA57_0 <= '\u19FF')||(LA57_0 >= '\u1D00' && LA57_0 <= '\u1D6B')||(LA57_0 >= '\u1E00' && LA57_0 <= '\u1E9B')||(LA57_0 >= '\u1EA0' && LA57_0 <= '\u1EF9')||(LA57_0 >= '\u1F00' && LA57_0 <= '\u1F15')||(LA57_0 >= '\u1F18' && LA57_0 <= '\u1F1D')||(LA57_0 >= '\u1F20' && LA57_0 <= '\u1F45')||(LA57_0 >= '\u1F48' && LA57_0 <= '\u1F4D')||(LA57_0 >= '\u1F50' && LA57_0 <= '\u1F57')||LA57_0=='\u1F59'||LA57_0=='\u1F5B'||LA57_0=='\u1F5D'||(LA57_0 >= '\u1F5F' && LA57_0 <= '\u1F7D')||(LA57_0 >= '\u1F80' && LA57_0 <= '\u1FB4')||(LA57_0 >= '\u1FB6' && LA57_0 <= '\u1FBC')||LA57_0=='\u1FBE'||(LA57_0 >= '\u1FC2' && LA57_0 <= '\u1FC4')||(LA57_0 >= '\u1FC6' && LA57_0 <= '\u1FCC')||(LA57_0 >= '\u1FD0' && LA57_0 <= '\u1FD3')||(LA57_0 >= '\u1FD6' && LA57_0 <= '\u1FDB')||(LA57_0 >= '\u1FE0' && LA57_0 <= '\u1FEC')||(LA57_0 >= '\u1FF2' && LA57_0 <= '\u1FF4')||(LA57_0 >= '\u1FF6' && LA57_0 <= '\u1FFC')||(LA57_0 >= '\u2070' && LA57_0 <= '\u2071')||(LA57_0 >= '\u2074' && LA57_0 <= '\u2079')||(LA57_0 >= '\u207F' && LA57_0 <= '\u2089')||(LA57_0 >= '\u20A0' && LA57_0 <= '\u20B1')||(LA57_0 >= '\u20D0' && LA57_0 <= '\u20EA')||(LA57_0 >= '\u2100' && LA57_0 <= '\u213B')||(LA57_0 >= '\u213D' && LA57_0 <= '\u213F')||(LA57_0 >= '\u2145' && LA57_0 <= '\u214A')||(LA57_0 >= '\u2153' && LA57_0 <= '\u2183')||(LA57_0 >= '\u2195' && LA57_0 <= '\u2199')||(LA57_0 >= '\u219C' && LA57_0 <= '\u219F')||(LA57_0 >= '\u21A1' && LA57_0 <= '\u21A2')||(LA57_0 >= '\u21A4' && LA57_0 <= '\u21A5')||(LA57_0 >= '\u21A7' && LA57_0 <= '\u21AD')||(LA57_0 >= '\u21AF' && LA57_0 <= '\u21CD')||(LA57_0 >= '\u21D0' && LA57_0 <= '\u21D1')||LA57_0=='\u21D3'||(LA57_0 >= '\u21D5' && LA57_0 <= '\u21F3')||(LA57_0 >= '\u2300' && LA57_0 <= '\u2307')||(LA57_0 >= '\u230C' && LA57_0 <= '\u231F')||(LA57_0 >= '\u2322' && LA57_0 <= '\u2328')||(LA57_0 >= '\u232B' && LA57_0 <= '\u237B')||(LA57_0 >= '\u237D' && LA57_0 <= '\u239A')||(LA57_0 >= '\u23B7' && LA57_0 <= '\u23D0')||(LA57_0 >= '\u2400' && LA57_0 <= '\u2426')||(LA57_0 >= '\u2440' && LA57_0 <= '\u244A')||(LA57_0 >= '\u2460' && LA57_0 <= '\u25B6')||(LA57_0 >= '\u25B8' && LA57_0 <= '\u25C0')||(LA57_0 >= '\u25C2' && LA57_0 <= '\u25F7')||(LA57_0 >= '\u2600' && LA57_0 <= '\u2617')||(LA57_0 >= '\u2619' && LA57_0 <= '\u266E')||(LA57_0 >= '\u2670' && LA57_0 <= '\u267D')||(LA57_0 >= '\u2680' && LA57_0 <= '\u2691')||(LA57_0 >= '\u26A0' && LA57_0 <= '\u26A1')||(LA57_0 >= '\u2701' && LA57_0 <= '\u2704')||(LA57_0 >= '\u2706' && LA57_0 <= '\u2709')||(LA57_0 >= '\u270C' && LA57_0 <= '\u2727')||(LA57_0 >= '\u2729' && LA57_0 <= '\u274B')||LA57_0=='\u274D'||(LA57_0 >= '\u274F' && LA57_0 <= '\u2752')||LA57_0=='\u2756'||(LA57_0 >= '\u2758' && LA57_0 <= '\u275E')||(LA57_0 >= '\u2761' && LA57_0 <= '\u2767')||(LA57_0 >= '\u2776' && LA57_0 <= '\u2794')||(LA57_0 >= '\u2798' && LA57_0 <= '\u27AF')||(LA57_0 >= '\u27B1' && LA57_0 <= '\u27BE')||(LA57_0 >= '\u2800' && LA57_0 <= '\u28FF')||(LA57_0 >= '\u2B00' && LA57_0 <= '\u2B0D')||(LA57_0 >= '\u2E80' && LA57_0 <= '\u2E99')||(LA57_0 >= '\u2E9B' && LA57_0 <= '\u2EF3')||(LA57_0 >= '\u2F00' && LA57_0 <= '\u2FD5')||(LA57_0 >= '\u2FF0' && LA57_0 <= '\u2FFB')||(LA57_0 >= '\u3004' && LA57_0 <= '\u3007')||(LA57_0 >= '\u3012' && LA57_0 <= '\u3013')||(LA57_0 >= '\u3020' && LA57_0 <= '\u302F')||(LA57_0 >= '\u3031' && LA57_0 <= '\u303C')||(LA57_0 >= '\u303E' && LA57_0 <= '\u303F')||(LA57_0 >= '\u3041' && LA57_0 <= '\u3096')||(LA57_0 >= '\u3099' && LA57_0 <= '\u309A')||(LA57_0 >= '\u309D' && LA57_0 <= '\u309F')||(LA57_0 >= '\u30A1' && LA57_0 <= '\u30FA')||(LA57_0 >= '\u30FC' && LA57_0 <= '\u30FF')||(LA57_0 >= '\u3105' && LA57_0 <= '\u312C')||(LA57_0 >= '\u3131' && LA57_0 <= '\u318E')||(LA57_0 >= '\u3190' && LA57_0 <= '\u31B7')||(LA57_0 >= '\u31F0' && LA57_0 <= '\u321E')||(LA57_0 >= '\u3220' && LA57_0 <= '\u3243')||(LA57_0 >= '\u3250' && LA57_0 <= '\u327D')||(LA57_0 >= '\u327F' && LA57_0 <= '\u32FE')||(LA57_0 >= '\u3300' && LA57_0 <= '\u4DB5')||(LA57_0 >= '\u4DC0' && LA57_0 <= '\u9FA5')||(LA57_0 >= '\uA000' && LA57_0 <= '\uA48C')||(LA57_0 >= '\uA490' && LA57_0 <= '\uA4C6')||(LA57_0 >= '\uAC00' && LA57_0 <= '\uD7A3')||(LA57_0 >= '\uF900' && LA57_0 <= '\uFA2D')||(LA57_0 >= '\uFA30' && LA57_0 <= '\uFA6A')||(LA57_0 >= '\uFB00' && LA57_0 <= '\uFB06')||(LA57_0 >= '\uFB13' && LA57_0 <= '\uFB17')||(LA57_0 >= '\uFB1D' && LA57_0 <= '\uFB28')||(LA57_0 >= '\uFB2A' && LA57_0 <= '\uFB36')||(LA57_0 >= '\uFB38' && LA57_0 <= '\uFB3C')||LA57_0=='\uFB3E'||(LA57_0 >= '\uFB40' && LA57_0 <= '\uFB41')||(LA57_0 >= '\uFB43' && LA57_0 <= '\uFB44')||(LA57_0 >= '\uFB46' && LA57_0 <= '\uFBB1')||(LA57_0 >= '\uFBD3' && LA57_0 <= '\uFD3D')||(LA57_0 >= '\uFD50' && LA57_0 <= '\uFD8F')||(LA57_0 >= '\uFD92' && LA57_0 <= '\uFDC7')||(LA57_0 >= '\uFDF0' && LA57_0 <= '\uFDFD')||(LA57_0 >= '\uFE00' && LA57_0 <= '\uFE0F')||(LA57_0 >= '\uFE20' && LA57_0 <= '\uFE23')||LA57_0=='\uFE69'||(LA57_0 >= '\uFE70' && LA57_0 <= '\uFE74')||(LA57_0 >= '\uFE76' && LA57_0 <= '\uFEFC')||LA57_0=='\uFF04'||(LA57_0 >= '\uFF10' && LA57_0 <= '\uFF19')||(LA57_0 >= '\uFF21' && LA57_0 <= '\uFF3A')||(LA57_0 >= '\uFF41' && LA57_0 <= '\uFF5A')||(LA57_0 >= '\uFF66' && LA57_0 <= '\uFFBE')||(LA57_0 >= '\uFFC2' && LA57_0 <= '\uFFC7')||(LA57_0 >= '\uFFCA' && LA57_0 <= '\uFFCF')||(LA57_0 >= '\uFFD2' && LA57_0 <= '\uFFD7')||(LA57_0 >= '\uFFDA' && LA57_0 <= '\uFFDC')||(LA57_0 >= '\uFFE0' && LA57_0 <= '\uFFE1')||(LA57_0 >= '\uFFE4' && LA57_0 <= '\uFFE6')||LA57_0=='\uFFE8'||(LA57_0 >= '\uFFED' && LA57_0 <= '\uFFEE')) ) { + alt57=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + NoViableAltException nvae = + new NoViableAltException("", 57, 0, input); + throw nvae; + } + + switch (alt57) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1523:17: F_ESC + { + mF_ESC(); if (state.failed) return; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1524:19: START_WORD + { + mSTART_WORD(); if (state.failed) return; + + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1526:9: ( F_ESC | IN_WORD )* + loop58: + while (true) { + int alt58=3; + int LA58_0 = input.LA(1); + if ( (LA58_0=='\\') ) { + alt58=1; + } + else if ( ((LA58_0 >= '!' && LA58_0 <= '\'')||LA58_0=='+'||LA58_0=='-'||(LA58_0 >= '/' && LA58_0 <= '9')||LA58_0==';'||LA58_0=='='||(LA58_0 >= '@' && LA58_0 <= 'Z')||LA58_0=='_'||(LA58_0 >= 'a' && LA58_0 <= 'z')||LA58_0=='|'||(LA58_0 >= '\u00A1' && LA58_0 <= '\u00A7')||(LA58_0 >= '\u00A9' && LA58_0 <= '\u00AA')||LA58_0=='\u00AC'||LA58_0=='\u00AE'||(LA58_0 >= '\u00B0' && LA58_0 <= '\u00B3')||(LA58_0 >= '\u00B5' && LA58_0 <= '\u00B7')||(LA58_0 >= '\u00B9' && LA58_0 <= '\u00BA')||(LA58_0 >= '\u00BC' && LA58_0 <= '\u0236')||(LA58_0 >= '\u0250' && LA58_0 <= '\u02C1')||(LA58_0 >= '\u02C6' && LA58_0 <= '\u02D1')||(LA58_0 >= '\u02E0' && LA58_0 <= '\u02E4')||LA58_0=='\u02EE'||(LA58_0 >= '\u0300' && LA58_0 <= '\u0357')||(LA58_0 >= '\u035D' && LA58_0 <= '\u036F')||LA58_0=='\u037A'||LA58_0=='\u037E'||(LA58_0 >= '\u0386' && LA58_0 <= '\u038A')||LA58_0=='\u038C'||(LA58_0 >= '\u038E' && LA58_0 <= '\u03A1')||(LA58_0 >= '\u03A3' && LA58_0 <= '\u03CE')||(LA58_0 >= '\u03D0' && LA58_0 <= '\u03FB')||(LA58_0 >= '\u0400' && LA58_0 <= '\u0486')||(LA58_0 >= '\u0488' && LA58_0 <= '\u04CE')||(LA58_0 >= '\u04D0' && LA58_0 <= '\u04F5')||(LA58_0 >= '\u04F8' && LA58_0 <= '\u04F9')||(LA58_0 >= '\u0500' && LA58_0 <= '\u050F')||(LA58_0 >= '\u0531' && LA58_0 <= '\u0556')||(LA58_0 >= '\u0559' && LA58_0 <= '\u055F')||(LA58_0 >= '\u0561' && LA58_0 <= '\u0587')||(LA58_0 >= '\u0589' && LA58_0 <= '\u058A')||(LA58_0 >= '\u0591' && LA58_0 <= '\u05A1')||(LA58_0 >= '\u05A3' && LA58_0 <= '\u05B9')||(LA58_0 >= '\u05BB' && LA58_0 <= '\u05C4')||(LA58_0 >= '\u05D0' && LA58_0 <= '\u05EA')||(LA58_0 >= '\u05F0' && LA58_0 <= '\u05F4')||(LA58_0 >= '\u060C' && LA58_0 <= '\u0615')||LA58_0=='\u061B'||LA58_0=='\u061F'||(LA58_0 >= '\u0621' && LA58_0 <= '\u063A')||(LA58_0 >= '\u0640' && LA58_0 <= '\u0658')||(LA58_0 >= '\u0660' && LA58_0 <= '\u06DC')||(LA58_0 >= '\u06DE' && LA58_0 <= '\u070D')||(LA58_0 >= '\u0710' && LA58_0 <= '\u074A')||(LA58_0 >= '\u074D' && LA58_0 <= '\u074F')||(LA58_0 >= '\u0780' && LA58_0 <= '\u07B1')||(LA58_0 >= '\u0901' && LA58_0 <= '\u0939')||(LA58_0 >= '\u093C' && LA58_0 <= '\u094D')||(LA58_0 >= '\u0950' && LA58_0 <= '\u0954')||(LA58_0 >= '\u0958' && LA58_0 <= '\u0970')||(LA58_0 >= '\u0981' && LA58_0 <= '\u0983')||(LA58_0 >= '\u0985' && LA58_0 <= '\u098C')||(LA58_0 >= '\u098F' && LA58_0 <= '\u0990')||(LA58_0 >= '\u0993' && LA58_0 <= '\u09A8')||(LA58_0 >= '\u09AA' && LA58_0 <= '\u09B0')||LA58_0=='\u09B2'||(LA58_0 >= '\u09B6' && LA58_0 <= '\u09B9')||(LA58_0 >= '\u09BC' && LA58_0 <= '\u09C4')||(LA58_0 >= '\u09C7' && LA58_0 <= '\u09C8')||(LA58_0 >= '\u09CB' && LA58_0 <= '\u09CD')||LA58_0=='\u09D7'||(LA58_0 >= '\u09DC' && LA58_0 <= '\u09DD')||(LA58_0 >= '\u09DF' && LA58_0 <= '\u09E3')||(LA58_0 >= '\u09E6' && LA58_0 <= '\u09FA')||(LA58_0 >= '\u0A01' && LA58_0 <= '\u0A03')||(LA58_0 >= '\u0A05' && LA58_0 <= '\u0A0A')||(LA58_0 >= '\u0A0F' && LA58_0 <= '\u0A10')||(LA58_0 >= '\u0A13' && LA58_0 <= '\u0A28')||(LA58_0 >= '\u0A2A' && LA58_0 <= '\u0A30')||(LA58_0 >= '\u0A32' && LA58_0 <= '\u0A33')||(LA58_0 >= '\u0A35' && LA58_0 <= '\u0A36')||(LA58_0 >= '\u0A38' && LA58_0 <= '\u0A39')||LA58_0=='\u0A3C'||(LA58_0 >= '\u0A3E' && LA58_0 <= '\u0A42')||(LA58_0 >= '\u0A47' && LA58_0 <= '\u0A48')||(LA58_0 >= '\u0A4B' && LA58_0 <= '\u0A4D')||(LA58_0 >= '\u0A59' && LA58_0 <= '\u0A5C')||LA58_0=='\u0A5E'||(LA58_0 >= '\u0A66' && LA58_0 <= '\u0A74')||(LA58_0 >= '\u0A81' && LA58_0 <= '\u0A83')||(LA58_0 >= '\u0A85' && LA58_0 <= '\u0A8D')||(LA58_0 >= '\u0A8F' && LA58_0 <= '\u0A91')||(LA58_0 >= '\u0A93' && LA58_0 <= '\u0AA8')||(LA58_0 >= '\u0AAA' && LA58_0 <= '\u0AB0')||(LA58_0 >= '\u0AB2' && LA58_0 <= '\u0AB3')||(LA58_0 >= '\u0AB5' && LA58_0 <= '\u0AB9')||(LA58_0 >= '\u0ABC' && LA58_0 <= '\u0AC5')||(LA58_0 >= '\u0AC7' && LA58_0 <= '\u0AC9')||(LA58_0 >= '\u0ACB' && LA58_0 <= '\u0ACD')||LA58_0=='\u0AD0'||(LA58_0 >= '\u0AE0' && LA58_0 <= '\u0AE3')||(LA58_0 >= '\u0AE6' && LA58_0 <= '\u0AEF')||LA58_0=='\u0AF1'||(LA58_0 >= '\u0B01' && LA58_0 <= '\u0B03')||(LA58_0 >= '\u0B05' && LA58_0 <= '\u0B0C')||(LA58_0 >= '\u0B0F' && LA58_0 <= '\u0B10')||(LA58_0 >= '\u0B13' && LA58_0 <= '\u0B28')||(LA58_0 >= '\u0B2A' && LA58_0 <= '\u0B30')||(LA58_0 >= '\u0B32' && LA58_0 <= '\u0B33')||(LA58_0 >= '\u0B35' && LA58_0 <= '\u0B39')||(LA58_0 >= '\u0B3C' && LA58_0 <= '\u0B43')||(LA58_0 >= '\u0B47' && LA58_0 <= '\u0B48')||(LA58_0 >= '\u0B4B' && LA58_0 <= '\u0B4D')||(LA58_0 >= '\u0B56' && LA58_0 <= '\u0B57')||(LA58_0 >= '\u0B5C' && LA58_0 <= '\u0B5D')||(LA58_0 >= '\u0B5F' && LA58_0 <= '\u0B61')||(LA58_0 >= '\u0B66' && LA58_0 <= '\u0B71')||(LA58_0 >= '\u0B82' && LA58_0 <= '\u0B83')||(LA58_0 >= '\u0B85' && LA58_0 <= '\u0B8A')||(LA58_0 >= '\u0B8E' && LA58_0 <= '\u0B90')||(LA58_0 >= '\u0B92' && LA58_0 <= '\u0B95')||(LA58_0 >= '\u0B99' && LA58_0 <= '\u0B9A')||LA58_0=='\u0B9C'||(LA58_0 >= '\u0B9E' && LA58_0 <= '\u0B9F')||(LA58_0 >= '\u0BA3' && LA58_0 <= '\u0BA4')||(LA58_0 >= '\u0BA8' && LA58_0 <= '\u0BAA')||(LA58_0 >= '\u0BAE' && LA58_0 <= '\u0BB5')||(LA58_0 >= '\u0BB7' && LA58_0 <= '\u0BB9')||(LA58_0 >= '\u0BBE' && LA58_0 <= '\u0BC2')||(LA58_0 >= '\u0BC6' && LA58_0 <= '\u0BC8')||(LA58_0 >= '\u0BCA' && LA58_0 <= '\u0BCD')||LA58_0=='\u0BD7'||(LA58_0 >= '\u0BE7' && LA58_0 <= '\u0BFA')||(LA58_0 >= '\u0C01' && LA58_0 <= '\u0C03')||(LA58_0 >= '\u0C05' && LA58_0 <= '\u0C0C')||(LA58_0 >= '\u0C0E' && LA58_0 <= '\u0C10')||(LA58_0 >= '\u0C12' && LA58_0 <= '\u0C28')||(LA58_0 >= '\u0C2A' && LA58_0 <= '\u0C33')||(LA58_0 >= '\u0C35' && LA58_0 <= '\u0C39')||(LA58_0 >= '\u0C3E' && LA58_0 <= '\u0C44')||(LA58_0 >= '\u0C46' && LA58_0 <= '\u0C48')||(LA58_0 >= '\u0C4A' && LA58_0 <= '\u0C4D')||(LA58_0 >= '\u0C55' && LA58_0 <= '\u0C56')||(LA58_0 >= '\u0C60' && LA58_0 <= '\u0C61')||(LA58_0 >= '\u0C66' && LA58_0 <= '\u0C6F')||(LA58_0 >= '\u0C82' && LA58_0 <= '\u0C83')||(LA58_0 >= '\u0C85' && LA58_0 <= '\u0C8C')||(LA58_0 >= '\u0C8E' && LA58_0 <= '\u0C90')||(LA58_0 >= '\u0C92' && LA58_0 <= '\u0CA8')||(LA58_0 >= '\u0CAA' && LA58_0 <= '\u0CB3')||(LA58_0 >= '\u0CB5' && LA58_0 <= '\u0CB9')||(LA58_0 >= '\u0CBC' && LA58_0 <= '\u0CC4')||(LA58_0 >= '\u0CC6' && LA58_0 <= '\u0CC8')||(LA58_0 >= '\u0CCA' && LA58_0 <= '\u0CCD')||(LA58_0 >= '\u0CD5' && LA58_0 <= '\u0CD6')||LA58_0=='\u0CDE'||(LA58_0 >= '\u0CE0' && LA58_0 <= '\u0CE1')||(LA58_0 >= '\u0CE6' && LA58_0 <= '\u0CEF')||(LA58_0 >= '\u0D02' && LA58_0 <= '\u0D03')||(LA58_0 >= '\u0D05' && LA58_0 <= '\u0D0C')||(LA58_0 >= '\u0D0E' && LA58_0 <= '\u0D10')||(LA58_0 >= '\u0D12' && LA58_0 <= '\u0D28')||(LA58_0 >= '\u0D2A' && LA58_0 <= '\u0D39')||(LA58_0 >= '\u0D3E' && LA58_0 <= '\u0D43')||(LA58_0 >= '\u0D46' && LA58_0 <= '\u0D48')||(LA58_0 >= '\u0D4A' && LA58_0 <= '\u0D4D')||LA58_0=='\u0D57'||(LA58_0 >= '\u0D60' && LA58_0 <= '\u0D61')||(LA58_0 >= '\u0D66' && LA58_0 <= '\u0D6F')||(LA58_0 >= '\u0D82' && LA58_0 <= '\u0D83')||(LA58_0 >= '\u0D85' && LA58_0 <= '\u0D96')||(LA58_0 >= '\u0D9A' && LA58_0 <= '\u0DB1')||(LA58_0 >= '\u0DB3' && LA58_0 <= '\u0DBB')||LA58_0=='\u0DBD'||(LA58_0 >= '\u0DC0' && LA58_0 <= '\u0DC6')||LA58_0=='\u0DCA'||(LA58_0 >= '\u0DCF' && LA58_0 <= '\u0DD4')||LA58_0=='\u0DD6'||(LA58_0 >= '\u0DD8' && LA58_0 <= '\u0DDF')||(LA58_0 >= '\u0DF2' && LA58_0 <= '\u0DF4')||(LA58_0 >= '\u0E01' && LA58_0 <= '\u0E3A')||(LA58_0 >= '\u0E3F' && LA58_0 <= '\u0E5B')||(LA58_0 >= '\u0E81' && LA58_0 <= '\u0E82')||LA58_0=='\u0E84'||(LA58_0 >= '\u0E87' && LA58_0 <= '\u0E88')||LA58_0=='\u0E8A'||LA58_0=='\u0E8D'||(LA58_0 >= '\u0E94' && LA58_0 <= '\u0E97')||(LA58_0 >= '\u0E99' && LA58_0 <= '\u0E9F')||(LA58_0 >= '\u0EA1' && LA58_0 <= '\u0EA3')||LA58_0=='\u0EA5'||LA58_0=='\u0EA7'||(LA58_0 >= '\u0EAA' && LA58_0 <= '\u0EAB')||(LA58_0 >= '\u0EAD' && LA58_0 <= '\u0EB9')||(LA58_0 >= '\u0EBB' && LA58_0 <= '\u0EBD')||(LA58_0 >= '\u0EC0' && LA58_0 <= '\u0EC4')||LA58_0=='\u0EC6'||(LA58_0 >= '\u0EC8' && LA58_0 <= '\u0ECD')||(LA58_0 >= '\u0ED0' && LA58_0 <= '\u0ED9')||(LA58_0 >= '\u0EDC' && LA58_0 <= '\u0EDD')||(LA58_0 >= '\u0F00' && LA58_0 <= '\u0F39')||(LA58_0 >= '\u0F3E' && LA58_0 <= '\u0F47')||(LA58_0 >= '\u0F49' && LA58_0 <= '\u0F6A')||(LA58_0 >= '\u0F71' && LA58_0 <= '\u0F8B')||(LA58_0 >= '\u0F90' && LA58_0 <= '\u0F97')||(LA58_0 >= '\u0F99' && LA58_0 <= '\u0FBC')||(LA58_0 >= '\u0FBE' && LA58_0 <= '\u0FCC')||LA58_0=='\u0FCF'||(LA58_0 >= '\u1000' && LA58_0 <= '\u1021')||(LA58_0 >= '\u1023' && LA58_0 <= '\u1027')||(LA58_0 >= '\u1029' && LA58_0 <= '\u102A')||(LA58_0 >= '\u102C' && LA58_0 <= '\u1032')||(LA58_0 >= '\u1036' && LA58_0 <= '\u1039')||(LA58_0 >= '\u1040' && LA58_0 <= '\u1059')||(LA58_0 >= '\u10A0' && LA58_0 <= '\u10C5')||(LA58_0 >= '\u10D0' && LA58_0 <= '\u10F8')||LA58_0=='\u10FB'||(LA58_0 >= '\u1100' && LA58_0 <= '\u1159')||(LA58_0 >= '\u115F' && LA58_0 <= '\u11A2')||(LA58_0 >= '\u11A8' && LA58_0 <= '\u11F9')||(LA58_0 >= '\u1200' && LA58_0 <= '\u1206')||(LA58_0 >= '\u1208' && LA58_0 <= '\u1246')||LA58_0=='\u1248'||(LA58_0 >= '\u124A' && LA58_0 <= '\u124D')||(LA58_0 >= '\u1250' && LA58_0 <= '\u1256')||LA58_0=='\u1258'||(LA58_0 >= '\u125A' && LA58_0 <= '\u125D')||(LA58_0 >= '\u1260' && LA58_0 <= '\u1286')||LA58_0=='\u1288'||(LA58_0 >= '\u128A' && LA58_0 <= '\u128D')||(LA58_0 >= '\u1290' && LA58_0 <= '\u12AE')||LA58_0=='\u12B0'||(LA58_0 >= '\u12B2' && LA58_0 <= '\u12B5')||(LA58_0 >= '\u12B8' && LA58_0 <= '\u12BE')||LA58_0=='\u12C0'||(LA58_0 >= '\u12C2' && LA58_0 <= '\u12C5')||(LA58_0 >= '\u12C8' && LA58_0 <= '\u12CE')||(LA58_0 >= '\u12D0' && LA58_0 <= '\u12D6')||(LA58_0 >= '\u12D8' && LA58_0 <= '\u12EE')||(LA58_0 >= '\u12F0' && LA58_0 <= '\u130E')||LA58_0=='\u1310'||(LA58_0 >= '\u1312' && LA58_0 <= '\u1315')||(LA58_0 >= '\u1318' && LA58_0 <= '\u131E')||(LA58_0 >= '\u1320' && LA58_0 <= '\u1346')||(LA58_0 >= '\u1348' && LA58_0 <= '\u135A')||(LA58_0 >= '\u1361' && LA58_0 <= '\u137C')||(LA58_0 >= '\u13A0' && LA58_0 <= '\u13F4')||(LA58_0 >= '\u1401' && LA58_0 <= '\u1676')||(LA58_0 >= '\u1681' && LA58_0 <= '\u169A')||(LA58_0 >= '\u16A0' && LA58_0 <= '\u16F0')||(LA58_0 >= '\u1700' && LA58_0 <= '\u170C')||(LA58_0 >= '\u170E' && LA58_0 <= '\u1714')||(LA58_0 >= '\u1720' && LA58_0 <= '\u1736')||(LA58_0 >= '\u1740' && LA58_0 <= '\u1753')||(LA58_0 >= '\u1760' && LA58_0 <= '\u176C')||(LA58_0 >= '\u176E' && LA58_0 <= '\u1770')||(LA58_0 >= '\u1772' && LA58_0 <= '\u1773')||(LA58_0 >= '\u1780' && LA58_0 <= '\u17B3')||(LA58_0 >= '\u17B6' && LA58_0 <= '\u17DD')||(LA58_0 >= '\u17E0' && LA58_0 <= '\u17E9')||(LA58_0 >= '\u17F0' && LA58_0 <= '\u17F9')||(LA58_0 >= '\u1800' && LA58_0 <= '\u180D')||(LA58_0 >= '\u1810' && LA58_0 <= '\u1819')||(LA58_0 >= '\u1820' && LA58_0 <= '\u1877')||(LA58_0 >= '\u1880' && LA58_0 <= '\u18A9')||(LA58_0 >= '\u1900' && LA58_0 <= '\u191C')||(LA58_0 >= '\u1920' && LA58_0 <= '\u192B')||(LA58_0 >= '\u1930' && LA58_0 <= '\u193B')||LA58_0=='\u1940'||(LA58_0 >= '\u1944' && LA58_0 <= '\u196D')||(LA58_0 >= '\u1970' && LA58_0 <= '\u1974')||(LA58_0 >= '\u19E0' && LA58_0 <= '\u19FF')||(LA58_0 >= '\u1D00' && LA58_0 <= '\u1D6B')||(LA58_0 >= '\u1E00' && LA58_0 <= '\u1E9B')||(LA58_0 >= '\u1EA0' && LA58_0 <= '\u1EF9')||(LA58_0 >= '\u1F00' && LA58_0 <= '\u1F15')||(LA58_0 >= '\u1F18' && LA58_0 <= '\u1F1D')||(LA58_0 >= '\u1F20' && LA58_0 <= '\u1F45')||(LA58_0 >= '\u1F48' && LA58_0 <= '\u1F4D')||(LA58_0 >= '\u1F50' && LA58_0 <= '\u1F57')||LA58_0=='\u1F59'||LA58_0=='\u1F5B'||LA58_0=='\u1F5D'||(LA58_0 >= '\u1F5F' && LA58_0 <= '\u1F7D')||(LA58_0 >= '\u1F80' && LA58_0 <= '\u1FB4')||(LA58_0 >= '\u1FB6' && LA58_0 <= '\u1FBC')||LA58_0=='\u1FBE'||(LA58_0 >= '\u1FC2' && LA58_0 <= '\u1FC4')||(LA58_0 >= '\u1FC6' && LA58_0 <= '\u1FCC')||(LA58_0 >= '\u1FD0' && LA58_0 <= '\u1FD3')||(LA58_0 >= '\u1FD6' && LA58_0 <= '\u1FDB')||(LA58_0 >= '\u1FE0' && LA58_0 <= '\u1FEC')||(LA58_0 >= '\u1FF2' && LA58_0 <= '\u1FF4')||(LA58_0 >= '\u1FF6' && LA58_0 <= '\u1FFC')||(LA58_0 >= '\u2010' && LA58_0 <= '\u2017')||(LA58_0 >= '\u2020' && LA58_0 <= '\u2027')||(LA58_0 >= '\u2030' && LA58_0 <= '\u2038')||(LA58_0 >= '\u203B' && LA58_0 <= '\u2044')||(LA58_0 >= '\u2047' && LA58_0 <= '\u2054')||LA58_0=='\u2057'||(LA58_0 >= '\u2070' && LA58_0 <= '\u2071')||(LA58_0 >= '\u2074' && LA58_0 <= '\u207C')||(LA58_0 >= '\u207F' && LA58_0 <= '\u208C')||(LA58_0 >= '\u20A0' && LA58_0 <= '\u20B1')||(LA58_0 >= '\u20D0' && LA58_0 <= '\u20EA')||(LA58_0 >= '\u2100' && LA58_0 <= '\u213B')||(LA58_0 >= '\u213D' && LA58_0 <= '\u214B')||(LA58_0 >= '\u2153' && LA58_0 <= '\u2183')||(LA58_0 >= '\u2190' && LA58_0 <= '\u2328')||(LA58_0 >= '\u232B' && LA58_0 <= '\u23B3')||(LA58_0 >= '\u23B6' && LA58_0 <= '\u23D0')||(LA58_0 >= '\u2400' && LA58_0 <= '\u2426')||(LA58_0 >= '\u2440' && LA58_0 <= '\u244A')||(LA58_0 >= '\u2460' && LA58_0 <= '\u2617')||(LA58_0 >= '\u2619' && LA58_0 <= '\u267D')||(LA58_0 >= '\u2680' && LA58_0 <= '\u2691')||(LA58_0 >= '\u26A0' && LA58_0 <= '\u26A1')||(LA58_0 >= '\u2701' && LA58_0 <= '\u2704')||(LA58_0 >= '\u2706' && LA58_0 <= '\u2709')||(LA58_0 >= '\u270C' && LA58_0 <= '\u2727')||(LA58_0 >= '\u2729' && LA58_0 <= '\u274B')||LA58_0=='\u274D'||(LA58_0 >= '\u274F' && LA58_0 <= '\u2752')||LA58_0=='\u2756'||(LA58_0 >= '\u2758' && LA58_0 <= '\u275E')||(LA58_0 >= '\u2761' && LA58_0 <= '\u2767')||(LA58_0 >= '\u2776' && LA58_0 <= '\u2794')||(LA58_0 >= '\u2798' && LA58_0 <= '\u27AF')||(LA58_0 >= '\u27B1' && LA58_0 <= '\u27BE')||(LA58_0 >= '\u27D0' && LA58_0 <= '\u27E5')||(LA58_0 >= '\u27F0' && LA58_0 <= '\u2982')||(LA58_0 >= '\u2999' && LA58_0 <= '\u29D7')||(LA58_0 >= '\u29DC' && LA58_0 <= '\u29FB')||(LA58_0 >= '\u29FE' && LA58_0 <= '\u2B0D')||(LA58_0 >= '\u2E80' && LA58_0 <= '\u2E99')||(LA58_0 >= '\u2E9B' && LA58_0 <= '\u2EF3')||(LA58_0 >= '\u2F00' && LA58_0 <= '\u2FD5')||(LA58_0 >= '\u2FF0' && LA58_0 <= '\u2FFB')||(LA58_0 >= '\u3001' && LA58_0 <= '\u3007')||(LA58_0 >= '\u3012' && LA58_0 <= '\u3013')||LA58_0=='\u301C'||(LA58_0 >= '\u3020' && LA58_0 <= '\u303F')||(LA58_0 >= '\u3041' && LA58_0 <= '\u3096')||(LA58_0 >= '\u3099' && LA58_0 <= '\u309A')||(LA58_0 >= '\u309D' && LA58_0 <= '\u30FF')||(LA58_0 >= '\u3105' && LA58_0 <= '\u312C')||(LA58_0 >= '\u3131' && LA58_0 <= '\u318E')||(LA58_0 >= '\u3190' && LA58_0 <= '\u31B7')||(LA58_0 >= '\u31F0' && LA58_0 <= '\u321E')||(LA58_0 >= '\u3220' && LA58_0 <= '\u3243')||(LA58_0 >= '\u3250' && LA58_0 <= '\u327D')||(LA58_0 >= '\u327F' && LA58_0 <= '\u32FE')||(LA58_0 >= '\u3300' && LA58_0 <= '\u4DB5')||(LA58_0 >= '\u4DC0' && LA58_0 <= '\u9FA5')||(LA58_0 >= '\uA000' && LA58_0 <= '\uA48C')||(LA58_0 >= '\uA490' && LA58_0 <= '\uA4C6')||(LA58_0 >= '\uAC00' && LA58_0 <= '\uD7A3')||(LA58_0 >= '\uF900' && LA58_0 <= '\uFA2D')||(LA58_0 >= '\uFA30' && LA58_0 <= '\uFA6A')||(LA58_0 >= '\uFB00' && LA58_0 <= '\uFB06')||(LA58_0 >= '\uFB13' && LA58_0 <= '\uFB17')||(LA58_0 >= '\uFB1D' && LA58_0 <= '\uFB36')||(LA58_0 >= '\uFB38' && LA58_0 <= '\uFB3C')||LA58_0=='\uFB3E'||(LA58_0 >= '\uFB40' && LA58_0 <= '\uFB41')||(LA58_0 >= '\uFB43' && LA58_0 <= '\uFB44')||(LA58_0 >= '\uFB46' && LA58_0 <= '\uFBB1')||(LA58_0 >= '\uFBD3' && LA58_0 <= '\uFD3D')||(LA58_0 >= '\uFD50' && LA58_0 <= '\uFD8F')||(LA58_0 >= '\uFD92' && LA58_0 <= '\uFDC7')||(LA58_0 >= '\uFDF0' && LA58_0 <= '\uFDFD')||(LA58_0 >= '\uFE00' && LA58_0 <= '\uFE0F')||(LA58_0 >= '\uFE20' && LA58_0 <= '\uFE23')||(LA58_0 >= '\uFE30' && LA58_0 <= '\uFE34')||(LA58_0 >= '\uFE45' && LA58_0 <= '\uFE46')||(LA58_0 >= '\uFE49' && LA58_0 <= '\uFE52')||(LA58_0 >= '\uFE54' && LA58_0 <= '\uFE58')||(LA58_0 >= '\uFE5F' && LA58_0 <= '\uFE66')||(LA58_0 >= '\uFE68' && LA58_0 <= '\uFE6B')||(LA58_0 >= '\uFE70' && LA58_0 <= '\uFE74')||(LA58_0 >= '\uFE76' && LA58_0 <= '\uFEFC')||(LA58_0 >= '\uFF01' && LA58_0 <= '\uFF07')||(LA58_0 >= '\uFF0A' && LA58_0 <= '\uFF3A')||LA58_0=='\uFF3C'||LA58_0=='\uFF3F'||(LA58_0 >= '\uFF41' && LA58_0 <= '\uFF5A')||LA58_0=='\uFF5C'||LA58_0=='\uFF5E'||LA58_0=='\uFF61'||(LA58_0 >= '\uFF64' && LA58_0 <= '\uFFBE')||(LA58_0 >= '\uFFC2' && LA58_0 <= '\uFFC7')||(LA58_0 >= '\uFFCA' && LA58_0 <= '\uFFCF')||(LA58_0 >= '\uFFD2' && LA58_0 <= '\uFFD7')||(LA58_0 >= '\uFFDA' && LA58_0 <= '\uFFDC')||(LA58_0 >= '\uFFE0' && LA58_0 <= '\uFFE2')||(LA58_0 >= '\uFFE4' && LA58_0 <= '\uFFE6')||(LA58_0 >= '\uFFE8' && LA58_0 <= '\uFFEE')) ) { + alt58=2; + } + + switch (alt58) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1527:17: F_ESC + { + mF_ESC(); if (state.failed) return; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1528:19: IN_WORD + { + mIN_WORD(); if (state.failed) return; + + } + break; + + default : + break loop58; + } + } + + mSTAR(); if (state.failed) return; + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "FTSPRE" + + // $ANTLR start "FTSWILD" + public final void mFTSWILD() throws RecognitionException { + try { + int _type = FTSWILD; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1534:9: ( ( F_ESC | START_WORD | STAR | QUESTION_MARK ) ( F_ESC | IN_WORD | STAR | QUESTION_MARK )* ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1535:9: ( F_ESC | START_WORD | STAR | QUESTION_MARK ) ( F_ESC | IN_WORD | STAR | QUESTION_MARK )* + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1535:9: ( F_ESC | START_WORD | STAR | QUESTION_MARK ) + int alt59=4; + int LA59_0 = input.LA(1); + if ( (LA59_0=='\\') ) { + alt59=1; + } + else if ( (LA59_0=='$'||(LA59_0 >= '0' && LA59_0 <= '9')||(LA59_0 >= 'A' && LA59_0 <= 'Z')||(LA59_0 >= 'a' && LA59_0 <= 'z')||(LA59_0 >= '\u00A2' && LA59_0 <= '\u00A7')||(LA59_0 >= '\u00A9' && LA59_0 <= '\u00AA')||LA59_0=='\u00AE'||LA59_0=='\u00B0'||(LA59_0 >= '\u00B2' && LA59_0 <= '\u00B3')||(LA59_0 >= '\u00B5' && LA59_0 <= '\u00B6')||(LA59_0 >= '\u00B9' && LA59_0 <= '\u00BA')||(LA59_0 >= '\u00BC' && LA59_0 <= '\u00BE')||(LA59_0 >= '\u00C0' && LA59_0 <= '\u00D6')||(LA59_0 >= '\u00D8' && LA59_0 <= '\u00F6')||(LA59_0 >= '\u00F8' && LA59_0 <= '\u0236')||(LA59_0 >= '\u0250' && LA59_0 <= '\u02C1')||(LA59_0 >= '\u02C6' && LA59_0 <= '\u02D1')||(LA59_0 >= '\u02E0' && LA59_0 <= '\u02E4')||LA59_0=='\u02EE'||(LA59_0 >= '\u0300' && LA59_0 <= '\u0357')||(LA59_0 >= '\u035D' && LA59_0 <= '\u036F')||LA59_0=='\u037A'||LA59_0=='\u0386'||(LA59_0 >= '\u0388' && LA59_0 <= '\u038A')||LA59_0=='\u038C'||(LA59_0 >= '\u038E' && LA59_0 <= '\u03A1')||(LA59_0 >= '\u03A3' && LA59_0 <= '\u03CE')||(LA59_0 >= '\u03D0' && LA59_0 <= '\u03F5')||(LA59_0 >= '\u03F7' && LA59_0 <= '\u03FB')||(LA59_0 >= '\u0400' && LA59_0 <= '\u0486')||(LA59_0 >= '\u0488' && LA59_0 <= '\u04CE')||(LA59_0 >= '\u04D0' && LA59_0 <= '\u04F5')||(LA59_0 >= '\u04F8' && LA59_0 <= '\u04F9')||(LA59_0 >= '\u0500' && LA59_0 <= '\u050F')||(LA59_0 >= '\u0531' && LA59_0 <= '\u0556')||LA59_0=='\u0559'||(LA59_0 >= '\u0561' && LA59_0 <= '\u0587')||(LA59_0 >= '\u0591' && LA59_0 <= '\u05A1')||(LA59_0 >= '\u05A3' && LA59_0 <= '\u05B9')||(LA59_0 >= '\u05BB' && LA59_0 <= '\u05BD')||LA59_0=='\u05BF'||(LA59_0 >= '\u05C1' && LA59_0 <= '\u05C2')||LA59_0=='\u05C4'||(LA59_0 >= '\u05D0' && LA59_0 <= '\u05EA')||(LA59_0 >= '\u05F0' && LA59_0 <= '\u05F2')||(LA59_0 >= '\u060E' && LA59_0 <= '\u0615')||(LA59_0 >= '\u0621' && LA59_0 <= '\u063A')||(LA59_0 >= '\u0640' && LA59_0 <= '\u0658')||(LA59_0 >= '\u0660' && LA59_0 <= '\u0669')||(LA59_0 >= '\u066E' && LA59_0 <= '\u06D3')||(LA59_0 >= '\u06D5' && LA59_0 <= '\u06DC')||(LA59_0 >= '\u06DE' && LA59_0 <= '\u06FF')||(LA59_0 >= '\u0710' && LA59_0 <= '\u074A')||(LA59_0 >= '\u074D' && LA59_0 <= '\u074F')||(LA59_0 >= '\u0780' && LA59_0 <= '\u07B1')||(LA59_0 >= '\u0901' && LA59_0 <= '\u0939')||(LA59_0 >= '\u093C' && LA59_0 <= '\u094D')||(LA59_0 >= '\u0950' && LA59_0 <= '\u0954')||(LA59_0 >= '\u0958' && LA59_0 <= '\u0963')||(LA59_0 >= '\u0966' && LA59_0 <= '\u096F')||(LA59_0 >= '\u0981' && LA59_0 <= '\u0983')||(LA59_0 >= '\u0985' && LA59_0 <= '\u098C')||(LA59_0 >= '\u098F' && LA59_0 <= '\u0990')||(LA59_0 >= '\u0993' && LA59_0 <= '\u09A8')||(LA59_0 >= '\u09AA' && LA59_0 <= '\u09B0')||LA59_0=='\u09B2'||(LA59_0 >= '\u09B6' && LA59_0 <= '\u09B9')||(LA59_0 >= '\u09BC' && LA59_0 <= '\u09C4')||(LA59_0 >= '\u09C7' && LA59_0 <= '\u09C8')||(LA59_0 >= '\u09CB' && LA59_0 <= '\u09CD')||LA59_0=='\u09D7'||(LA59_0 >= '\u09DC' && LA59_0 <= '\u09DD')||(LA59_0 >= '\u09DF' && LA59_0 <= '\u09E3')||(LA59_0 >= '\u09E6' && LA59_0 <= '\u09FA')||(LA59_0 >= '\u0A01' && LA59_0 <= '\u0A03')||(LA59_0 >= '\u0A05' && LA59_0 <= '\u0A0A')||(LA59_0 >= '\u0A0F' && LA59_0 <= '\u0A10')||(LA59_0 >= '\u0A13' && LA59_0 <= '\u0A28')||(LA59_0 >= '\u0A2A' && LA59_0 <= '\u0A30')||(LA59_0 >= '\u0A32' && LA59_0 <= '\u0A33')||(LA59_0 >= '\u0A35' && LA59_0 <= '\u0A36')||(LA59_0 >= '\u0A38' && LA59_0 <= '\u0A39')||LA59_0=='\u0A3C'||(LA59_0 >= '\u0A3E' && LA59_0 <= '\u0A42')||(LA59_0 >= '\u0A47' && LA59_0 <= '\u0A48')||(LA59_0 >= '\u0A4B' && LA59_0 <= '\u0A4D')||(LA59_0 >= '\u0A59' && LA59_0 <= '\u0A5C')||LA59_0=='\u0A5E'||(LA59_0 >= '\u0A66' && LA59_0 <= '\u0A74')||(LA59_0 >= '\u0A81' && LA59_0 <= '\u0A83')||(LA59_0 >= '\u0A85' && LA59_0 <= '\u0A8D')||(LA59_0 >= '\u0A8F' && LA59_0 <= '\u0A91')||(LA59_0 >= '\u0A93' && LA59_0 <= '\u0AA8')||(LA59_0 >= '\u0AAA' && LA59_0 <= '\u0AB0')||(LA59_0 >= '\u0AB2' && LA59_0 <= '\u0AB3')||(LA59_0 >= '\u0AB5' && LA59_0 <= '\u0AB9')||(LA59_0 >= '\u0ABC' && LA59_0 <= '\u0AC5')||(LA59_0 >= '\u0AC7' && LA59_0 <= '\u0AC9')||(LA59_0 >= '\u0ACB' && LA59_0 <= '\u0ACD')||LA59_0=='\u0AD0'||(LA59_0 >= '\u0AE0' && LA59_0 <= '\u0AE3')||(LA59_0 >= '\u0AE6' && LA59_0 <= '\u0AEF')||LA59_0=='\u0AF1'||(LA59_0 >= '\u0B01' && LA59_0 <= '\u0B03')||(LA59_0 >= '\u0B05' && LA59_0 <= '\u0B0C')||(LA59_0 >= '\u0B0F' && LA59_0 <= '\u0B10')||(LA59_0 >= '\u0B13' && LA59_0 <= '\u0B28')||(LA59_0 >= '\u0B2A' && LA59_0 <= '\u0B30')||(LA59_0 >= '\u0B32' && LA59_0 <= '\u0B33')||(LA59_0 >= '\u0B35' && LA59_0 <= '\u0B39')||(LA59_0 >= '\u0B3C' && LA59_0 <= '\u0B43')||(LA59_0 >= '\u0B47' && LA59_0 <= '\u0B48')||(LA59_0 >= '\u0B4B' && LA59_0 <= '\u0B4D')||(LA59_0 >= '\u0B56' && LA59_0 <= '\u0B57')||(LA59_0 >= '\u0B5C' && LA59_0 <= '\u0B5D')||(LA59_0 >= '\u0B5F' && LA59_0 <= '\u0B61')||(LA59_0 >= '\u0B66' && LA59_0 <= '\u0B71')||(LA59_0 >= '\u0B82' && LA59_0 <= '\u0B83')||(LA59_0 >= '\u0B85' && LA59_0 <= '\u0B8A')||(LA59_0 >= '\u0B8E' && LA59_0 <= '\u0B90')||(LA59_0 >= '\u0B92' && LA59_0 <= '\u0B95')||(LA59_0 >= '\u0B99' && LA59_0 <= '\u0B9A')||LA59_0=='\u0B9C'||(LA59_0 >= '\u0B9E' && LA59_0 <= '\u0B9F')||(LA59_0 >= '\u0BA3' && LA59_0 <= '\u0BA4')||(LA59_0 >= '\u0BA8' && LA59_0 <= '\u0BAA')||(LA59_0 >= '\u0BAE' && LA59_0 <= '\u0BB5')||(LA59_0 >= '\u0BB7' && LA59_0 <= '\u0BB9')||(LA59_0 >= '\u0BBE' && LA59_0 <= '\u0BC2')||(LA59_0 >= '\u0BC6' && LA59_0 <= '\u0BC8')||(LA59_0 >= '\u0BCA' && LA59_0 <= '\u0BCD')||LA59_0=='\u0BD7'||(LA59_0 >= '\u0BE7' && LA59_0 <= '\u0BFA')||(LA59_0 >= '\u0C01' && LA59_0 <= '\u0C03')||(LA59_0 >= '\u0C05' && LA59_0 <= '\u0C0C')||(LA59_0 >= '\u0C0E' && LA59_0 <= '\u0C10')||(LA59_0 >= '\u0C12' && LA59_0 <= '\u0C28')||(LA59_0 >= '\u0C2A' && LA59_0 <= '\u0C33')||(LA59_0 >= '\u0C35' && LA59_0 <= '\u0C39')||(LA59_0 >= '\u0C3E' && LA59_0 <= '\u0C44')||(LA59_0 >= '\u0C46' && LA59_0 <= '\u0C48')||(LA59_0 >= '\u0C4A' && LA59_0 <= '\u0C4D')||(LA59_0 >= '\u0C55' && LA59_0 <= '\u0C56')||(LA59_0 >= '\u0C60' && LA59_0 <= '\u0C61')||(LA59_0 >= '\u0C66' && LA59_0 <= '\u0C6F')||(LA59_0 >= '\u0C82' && LA59_0 <= '\u0C83')||(LA59_0 >= '\u0C85' && LA59_0 <= '\u0C8C')||(LA59_0 >= '\u0C8E' && LA59_0 <= '\u0C90')||(LA59_0 >= '\u0C92' && LA59_0 <= '\u0CA8')||(LA59_0 >= '\u0CAA' && LA59_0 <= '\u0CB3')||(LA59_0 >= '\u0CB5' && LA59_0 <= '\u0CB9')||(LA59_0 >= '\u0CBC' && LA59_0 <= '\u0CC4')||(LA59_0 >= '\u0CC6' && LA59_0 <= '\u0CC8')||(LA59_0 >= '\u0CCA' && LA59_0 <= '\u0CCD')||(LA59_0 >= '\u0CD5' && LA59_0 <= '\u0CD6')||LA59_0=='\u0CDE'||(LA59_0 >= '\u0CE0' && LA59_0 <= '\u0CE1')||(LA59_0 >= '\u0CE6' && LA59_0 <= '\u0CEF')||(LA59_0 >= '\u0D02' && LA59_0 <= '\u0D03')||(LA59_0 >= '\u0D05' && LA59_0 <= '\u0D0C')||(LA59_0 >= '\u0D0E' && LA59_0 <= '\u0D10')||(LA59_0 >= '\u0D12' && LA59_0 <= '\u0D28')||(LA59_0 >= '\u0D2A' && LA59_0 <= '\u0D39')||(LA59_0 >= '\u0D3E' && LA59_0 <= '\u0D43')||(LA59_0 >= '\u0D46' && LA59_0 <= '\u0D48')||(LA59_0 >= '\u0D4A' && LA59_0 <= '\u0D4D')||LA59_0=='\u0D57'||(LA59_0 >= '\u0D60' && LA59_0 <= '\u0D61')||(LA59_0 >= '\u0D66' && LA59_0 <= '\u0D6F')||(LA59_0 >= '\u0D82' && LA59_0 <= '\u0D83')||(LA59_0 >= '\u0D85' && LA59_0 <= '\u0D96')||(LA59_0 >= '\u0D9A' && LA59_0 <= '\u0DB1')||(LA59_0 >= '\u0DB3' && LA59_0 <= '\u0DBB')||LA59_0=='\u0DBD'||(LA59_0 >= '\u0DC0' && LA59_0 <= '\u0DC6')||LA59_0=='\u0DCA'||(LA59_0 >= '\u0DCF' && LA59_0 <= '\u0DD4')||LA59_0=='\u0DD6'||(LA59_0 >= '\u0DD8' && LA59_0 <= '\u0DDF')||(LA59_0 >= '\u0DF2' && LA59_0 <= '\u0DF3')||(LA59_0 >= '\u0E01' && LA59_0 <= '\u0E3A')||(LA59_0 >= '\u0E3F' && LA59_0 <= '\u0E4E')||(LA59_0 >= '\u0E50' && LA59_0 <= '\u0E59')||(LA59_0 >= '\u0E81' && LA59_0 <= '\u0E82')||LA59_0=='\u0E84'||(LA59_0 >= '\u0E87' && LA59_0 <= '\u0E88')||LA59_0=='\u0E8A'||LA59_0=='\u0E8D'||(LA59_0 >= '\u0E94' && LA59_0 <= '\u0E97')||(LA59_0 >= '\u0E99' && LA59_0 <= '\u0E9F')||(LA59_0 >= '\u0EA1' && LA59_0 <= '\u0EA3')||LA59_0=='\u0EA5'||LA59_0=='\u0EA7'||(LA59_0 >= '\u0EAA' && LA59_0 <= '\u0EAB')||(LA59_0 >= '\u0EAD' && LA59_0 <= '\u0EB9')||(LA59_0 >= '\u0EBB' && LA59_0 <= '\u0EBD')||(LA59_0 >= '\u0EC0' && LA59_0 <= '\u0EC4')||LA59_0=='\u0EC6'||(LA59_0 >= '\u0EC8' && LA59_0 <= '\u0ECD')||(LA59_0 >= '\u0ED0' && LA59_0 <= '\u0ED9')||(LA59_0 >= '\u0EDC' && LA59_0 <= '\u0EDD')||(LA59_0 >= '\u0F00' && LA59_0 <= '\u0F03')||(LA59_0 >= '\u0F13' && LA59_0 <= '\u0F39')||(LA59_0 >= '\u0F3E' && LA59_0 <= '\u0F47')||(LA59_0 >= '\u0F49' && LA59_0 <= '\u0F6A')||(LA59_0 >= '\u0F71' && LA59_0 <= '\u0F84')||(LA59_0 >= '\u0F86' && LA59_0 <= '\u0F8B')||(LA59_0 >= '\u0F90' && LA59_0 <= '\u0F97')||(LA59_0 >= '\u0F99' && LA59_0 <= '\u0FBC')||(LA59_0 >= '\u0FBE' && LA59_0 <= '\u0FCC')||LA59_0=='\u0FCF'||(LA59_0 >= '\u1000' && LA59_0 <= '\u1021')||(LA59_0 >= '\u1023' && LA59_0 <= '\u1027')||(LA59_0 >= '\u1029' && LA59_0 <= '\u102A')||(LA59_0 >= '\u102C' && LA59_0 <= '\u1032')||(LA59_0 >= '\u1036' && LA59_0 <= '\u1039')||(LA59_0 >= '\u1040' && LA59_0 <= '\u1049')||(LA59_0 >= '\u1050' && LA59_0 <= '\u1059')||(LA59_0 >= '\u10A0' && LA59_0 <= '\u10C5')||(LA59_0 >= '\u10D0' && LA59_0 <= '\u10F8')||(LA59_0 >= '\u1100' && LA59_0 <= '\u1159')||(LA59_0 >= '\u115F' && LA59_0 <= '\u11A2')||(LA59_0 >= '\u11A8' && LA59_0 <= '\u11F9')||(LA59_0 >= '\u1200' && LA59_0 <= '\u1206')||(LA59_0 >= '\u1208' && LA59_0 <= '\u1246')||LA59_0=='\u1248'||(LA59_0 >= '\u124A' && LA59_0 <= '\u124D')||(LA59_0 >= '\u1250' && LA59_0 <= '\u1256')||LA59_0=='\u1258'||(LA59_0 >= '\u125A' && LA59_0 <= '\u125D')||(LA59_0 >= '\u1260' && LA59_0 <= '\u1286')||LA59_0=='\u1288'||(LA59_0 >= '\u128A' && LA59_0 <= '\u128D')||(LA59_0 >= '\u1290' && LA59_0 <= '\u12AE')||LA59_0=='\u12B0'||(LA59_0 >= '\u12B2' && LA59_0 <= '\u12B5')||(LA59_0 >= '\u12B8' && LA59_0 <= '\u12BE')||LA59_0=='\u12C0'||(LA59_0 >= '\u12C2' && LA59_0 <= '\u12C5')||(LA59_0 >= '\u12C8' && LA59_0 <= '\u12CE')||(LA59_0 >= '\u12D0' && LA59_0 <= '\u12D6')||(LA59_0 >= '\u12D8' && LA59_0 <= '\u12EE')||(LA59_0 >= '\u12F0' && LA59_0 <= '\u130E')||LA59_0=='\u1310'||(LA59_0 >= '\u1312' && LA59_0 <= '\u1315')||(LA59_0 >= '\u1318' && LA59_0 <= '\u131E')||(LA59_0 >= '\u1320' && LA59_0 <= '\u1346')||(LA59_0 >= '\u1348' && LA59_0 <= '\u135A')||(LA59_0 >= '\u1369' && LA59_0 <= '\u137C')||(LA59_0 >= '\u13A0' && LA59_0 <= '\u13F4')||(LA59_0 >= '\u1401' && LA59_0 <= '\u166C')||(LA59_0 >= '\u166F' && LA59_0 <= '\u1676')||(LA59_0 >= '\u1681' && LA59_0 <= '\u169A')||(LA59_0 >= '\u16A0' && LA59_0 <= '\u16EA')||(LA59_0 >= '\u16EE' && LA59_0 <= '\u16F0')||(LA59_0 >= '\u1700' && LA59_0 <= '\u170C')||(LA59_0 >= '\u170E' && LA59_0 <= '\u1714')||(LA59_0 >= '\u1720' && LA59_0 <= '\u1734')||(LA59_0 >= '\u1740' && LA59_0 <= '\u1753')||(LA59_0 >= '\u1760' && LA59_0 <= '\u176C')||(LA59_0 >= '\u176E' && LA59_0 <= '\u1770')||(LA59_0 >= '\u1772' && LA59_0 <= '\u1773')||(LA59_0 >= '\u1780' && LA59_0 <= '\u17B3')||(LA59_0 >= '\u17B6' && LA59_0 <= '\u17D3')||LA59_0=='\u17D7'||(LA59_0 >= '\u17DB' && LA59_0 <= '\u17DD')||(LA59_0 >= '\u17E0' && LA59_0 <= '\u17E9')||(LA59_0 >= '\u17F0' && LA59_0 <= '\u17F9')||(LA59_0 >= '\u180B' && LA59_0 <= '\u180D')||(LA59_0 >= '\u1810' && LA59_0 <= '\u1819')||(LA59_0 >= '\u1820' && LA59_0 <= '\u1877')||(LA59_0 >= '\u1880' && LA59_0 <= '\u18A9')||(LA59_0 >= '\u1900' && LA59_0 <= '\u191C')||(LA59_0 >= '\u1920' && LA59_0 <= '\u192B')||(LA59_0 >= '\u1930' && LA59_0 <= '\u193B')||LA59_0=='\u1940'||(LA59_0 >= '\u1946' && LA59_0 <= '\u196D')||(LA59_0 >= '\u1970' && LA59_0 <= '\u1974')||(LA59_0 >= '\u19E0' && LA59_0 <= '\u19FF')||(LA59_0 >= '\u1D00' && LA59_0 <= '\u1D6B')||(LA59_0 >= '\u1E00' && LA59_0 <= '\u1E9B')||(LA59_0 >= '\u1EA0' && LA59_0 <= '\u1EF9')||(LA59_0 >= '\u1F00' && LA59_0 <= '\u1F15')||(LA59_0 >= '\u1F18' && LA59_0 <= '\u1F1D')||(LA59_0 >= '\u1F20' && LA59_0 <= '\u1F45')||(LA59_0 >= '\u1F48' && LA59_0 <= '\u1F4D')||(LA59_0 >= '\u1F50' && LA59_0 <= '\u1F57')||LA59_0=='\u1F59'||LA59_0=='\u1F5B'||LA59_0=='\u1F5D'||(LA59_0 >= '\u1F5F' && LA59_0 <= '\u1F7D')||(LA59_0 >= '\u1F80' && LA59_0 <= '\u1FB4')||(LA59_0 >= '\u1FB6' && LA59_0 <= '\u1FBC')||LA59_0=='\u1FBE'||(LA59_0 >= '\u1FC2' && LA59_0 <= '\u1FC4')||(LA59_0 >= '\u1FC6' && LA59_0 <= '\u1FCC')||(LA59_0 >= '\u1FD0' && LA59_0 <= '\u1FD3')||(LA59_0 >= '\u1FD6' && LA59_0 <= '\u1FDB')||(LA59_0 >= '\u1FE0' && LA59_0 <= '\u1FEC')||(LA59_0 >= '\u1FF2' && LA59_0 <= '\u1FF4')||(LA59_0 >= '\u1FF6' && LA59_0 <= '\u1FFC')||(LA59_0 >= '\u2070' && LA59_0 <= '\u2071')||(LA59_0 >= '\u2074' && LA59_0 <= '\u2079')||(LA59_0 >= '\u207F' && LA59_0 <= '\u2089')||(LA59_0 >= '\u20A0' && LA59_0 <= '\u20B1')||(LA59_0 >= '\u20D0' && LA59_0 <= '\u20EA')||(LA59_0 >= '\u2100' && LA59_0 <= '\u213B')||(LA59_0 >= '\u213D' && LA59_0 <= '\u213F')||(LA59_0 >= '\u2145' && LA59_0 <= '\u214A')||(LA59_0 >= '\u2153' && LA59_0 <= '\u2183')||(LA59_0 >= '\u2195' && LA59_0 <= '\u2199')||(LA59_0 >= '\u219C' && LA59_0 <= '\u219F')||(LA59_0 >= '\u21A1' && LA59_0 <= '\u21A2')||(LA59_0 >= '\u21A4' && LA59_0 <= '\u21A5')||(LA59_0 >= '\u21A7' && LA59_0 <= '\u21AD')||(LA59_0 >= '\u21AF' && LA59_0 <= '\u21CD')||(LA59_0 >= '\u21D0' && LA59_0 <= '\u21D1')||LA59_0=='\u21D3'||(LA59_0 >= '\u21D5' && LA59_0 <= '\u21F3')||(LA59_0 >= '\u2300' && LA59_0 <= '\u2307')||(LA59_0 >= '\u230C' && LA59_0 <= '\u231F')||(LA59_0 >= '\u2322' && LA59_0 <= '\u2328')||(LA59_0 >= '\u232B' && LA59_0 <= '\u237B')||(LA59_0 >= '\u237D' && LA59_0 <= '\u239A')||(LA59_0 >= '\u23B7' && LA59_0 <= '\u23D0')||(LA59_0 >= '\u2400' && LA59_0 <= '\u2426')||(LA59_0 >= '\u2440' && LA59_0 <= '\u244A')||(LA59_0 >= '\u2460' && LA59_0 <= '\u25B6')||(LA59_0 >= '\u25B8' && LA59_0 <= '\u25C0')||(LA59_0 >= '\u25C2' && LA59_0 <= '\u25F7')||(LA59_0 >= '\u2600' && LA59_0 <= '\u2617')||(LA59_0 >= '\u2619' && LA59_0 <= '\u266E')||(LA59_0 >= '\u2670' && LA59_0 <= '\u267D')||(LA59_0 >= '\u2680' && LA59_0 <= '\u2691')||(LA59_0 >= '\u26A0' && LA59_0 <= '\u26A1')||(LA59_0 >= '\u2701' && LA59_0 <= '\u2704')||(LA59_0 >= '\u2706' && LA59_0 <= '\u2709')||(LA59_0 >= '\u270C' && LA59_0 <= '\u2727')||(LA59_0 >= '\u2729' && LA59_0 <= '\u274B')||LA59_0=='\u274D'||(LA59_0 >= '\u274F' && LA59_0 <= '\u2752')||LA59_0=='\u2756'||(LA59_0 >= '\u2758' && LA59_0 <= '\u275E')||(LA59_0 >= '\u2761' && LA59_0 <= '\u2767')||(LA59_0 >= '\u2776' && LA59_0 <= '\u2794')||(LA59_0 >= '\u2798' && LA59_0 <= '\u27AF')||(LA59_0 >= '\u27B1' && LA59_0 <= '\u27BE')||(LA59_0 >= '\u2800' && LA59_0 <= '\u28FF')||(LA59_0 >= '\u2B00' && LA59_0 <= '\u2B0D')||(LA59_0 >= '\u2E80' && LA59_0 <= '\u2E99')||(LA59_0 >= '\u2E9B' && LA59_0 <= '\u2EF3')||(LA59_0 >= '\u2F00' && LA59_0 <= '\u2FD5')||(LA59_0 >= '\u2FF0' && LA59_0 <= '\u2FFB')||(LA59_0 >= '\u3004' && LA59_0 <= '\u3007')||(LA59_0 >= '\u3012' && LA59_0 <= '\u3013')||(LA59_0 >= '\u3020' && LA59_0 <= '\u302F')||(LA59_0 >= '\u3031' && LA59_0 <= '\u303C')||(LA59_0 >= '\u303E' && LA59_0 <= '\u303F')||(LA59_0 >= '\u3041' && LA59_0 <= '\u3096')||(LA59_0 >= '\u3099' && LA59_0 <= '\u309A')||(LA59_0 >= '\u309D' && LA59_0 <= '\u309F')||(LA59_0 >= '\u30A1' && LA59_0 <= '\u30FA')||(LA59_0 >= '\u30FC' && LA59_0 <= '\u30FF')||(LA59_0 >= '\u3105' && LA59_0 <= '\u312C')||(LA59_0 >= '\u3131' && LA59_0 <= '\u318E')||(LA59_0 >= '\u3190' && LA59_0 <= '\u31B7')||(LA59_0 >= '\u31F0' && LA59_0 <= '\u321E')||(LA59_0 >= '\u3220' && LA59_0 <= '\u3243')||(LA59_0 >= '\u3250' && LA59_0 <= '\u327D')||(LA59_0 >= '\u327F' && LA59_0 <= '\u32FE')||(LA59_0 >= '\u3300' && LA59_0 <= '\u4DB5')||(LA59_0 >= '\u4DC0' && LA59_0 <= '\u9FA5')||(LA59_0 >= '\uA000' && LA59_0 <= '\uA48C')||(LA59_0 >= '\uA490' && LA59_0 <= '\uA4C6')||(LA59_0 >= '\uAC00' && LA59_0 <= '\uD7A3')||(LA59_0 >= '\uF900' && LA59_0 <= '\uFA2D')||(LA59_0 >= '\uFA30' && LA59_0 <= '\uFA6A')||(LA59_0 >= '\uFB00' && LA59_0 <= '\uFB06')||(LA59_0 >= '\uFB13' && LA59_0 <= '\uFB17')||(LA59_0 >= '\uFB1D' && LA59_0 <= '\uFB28')||(LA59_0 >= '\uFB2A' && LA59_0 <= '\uFB36')||(LA59_0 >= '\uFB38' && LA59_0 <= '\uFB3C')||LA59_0=='\uFB3E'||(LA59_0 >= '\uFB40' && LA59_0 <= '\uFB41')||(LA59_0 >= '\uFB43' && LA59_0 <= '\uFB44')||(LA59_0 >= '\uFB46' && LA59_0 <= '\uFBB1')||(LA59_0 >= '\uFBD3' && LA59_0 <= '\uFD3D')||(LA59_0 >= '\uFD50' && LA59_0 <= '\uFD8F')||(LA59_0 >= '\uFD92' && LA59_0 <= '\uFDC7')||(LA59_0 >= '\uFDF0' && LA59_0 <= '\uFDFD')||(LA59_0 >= '\uFE00' && LA59_0 <= '\uFE0F')||(LA59_0 >= '\uFE20' && LA59_0 <= '\uFE23')||LA59_0=='\uFE69'||(LA59_0 >= '\uFE70' && LA59_0 <= '\uFE74')||(LA59_0 >= '\uFE76' && LA59_0 <= '\uFEFC')||LA59_0=='\uFF04'||(LA59_0 >= '\uFF10' && LA59_0 <= '\uFF19')||(LA59_0 >= '\uFF21' && LA59_0 <= '\uFF3A')||(LA59_0 >= '\uFF41' && LA59_0 <= '\uFF5A')||(LA59_0 >= '\uFF66' && LA59_0 <= '\uFFBE')||(LA59_0 >= '\uFFC2' && LA59_0 <= '\uFFC7')||(LA59_0 >= '\uFFCA' && LA59_0 <= '\uFFCF')||(LA59_0 >= '\uFFD2' && LA59_0 <= '\uFFD7')||(LA59_0 >= '\uFFDA' && LA59_0 <= '\uFFDC')||(LA59_0 >= '\uFFE0' && LA59_0 <= '\uFFE1')||(LA59_0 >= '\uFFE4' && LA59_0 <= '\uFFE6')||LA59_0=='\uFFE8'||(LA59_0 >= '\uFFED' && LA59_0 <= '\uFFEE')) ) { + alt59=2; + } + else if ( (LA59_0=='*') ) { + alt59=3; + } + else if ( (LA59_0=='?') ) { + alt59=4; + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + NoViableAltException nvae = + new NoViableAltException("", 59, 0, input); + throw nvae; + } + + switch (alt59) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1536:17: F_ESC + { + mF_ESC(); if (state.failed) return; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1537:19: START_WORD + { + mSTART_WORD(); if (state.failed) return; + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1538:19: STAR + { + mSTAR(); if (state.failed) return; + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1539:19: QUESTION_MARK + { + mQUESTION_MARK(); if (state.failed) return; + + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1541:9: ( F_ESC | IN_WORD | STAR | QUESTION_MARK )* + loop60: + while (true) { + int alt60=5; + int LA60_0 = input.LA(1); + if ( (LA60_0=='\\') ) { + alt60=1; + } + else if ( ((LA60_0 >= '!' && LA60_0 <= '\'')||LA60_0=='+'||LA60_0=='-'||(LA60_0 >= '/' && LA60_0 <= '9')||LA60_0==';'||LA60_0=='='||(LA60_0 >= '@' && LA60_0 <= 'Z')||LA60_0=='_'||(LA60_0 >= 'a' && LA60_0 <= 'z')||LA60_0=='|'||(LA60_0 >= '\u00A1' && LA60_0 <= '\u00A7')||(LA60_0 >= '\u00A9' && LA60_0 <= '\u00AA')||LA60_0=='\u00AC'||LA60_0=='\u00AE'||(LA60_0 >= '\u00B0' && LA60_0 <= '\u00B3')||(LA60_0 >= '\u00B5' && LA60_0 <= '\u00B7')||(LA60_0 >= '\u00B9' && LA60_0 <= '\u00BA')||(LA60_0 >= '\u00BC' && LA60_0 <= '\u0236')||(LA60_0 >= '\u0250' && LA60_0 <= '\u02C1')||(LA60_0 >= '\u02C6' && LA60_0 <= '\u02D1')||(LA60_0 >= '\u02E0' && LA60_0 <= '\u02E4')||LA60_0=='\u02EE'||(LA60_0 >= '\u0300' && LA60_0 <= '\u0357')||(LA60_0 >= '\u035D' && LA60_0 <= '\u036F')||LA60_0=='\u037A'||LA60_0=='\u037E'||(LA60_0 >= '\u0386' && LA60_0 <= '\u038A')||LA60_0=='\u038C'||(LA60_0 >= '\u038E' && LA60_0 <= '\u03A1')||(LA60_0 >= '\u03A3' && LA60_0 <= '\u03CE')||(LA60_0 >= '\u03D0' && LA60_0 <= '\u03FB')||(LA60_0 >= '\u0400' && LA60_0 <= '\u0486')||(LA60_0 >= '\u0488' && LA60_0 <= '\u04CE')||(LA60_0 >= '\u04D0' && LA60_0 <= '\u04F5')||(LA60_0 >= '\u04F8' && LA60_0 <= '\u04F9')||(LA60_0 >= '\u0500' && LA60_0 <= '\u050F')||(LA60_0 >= '\u0531' && LA60_0 <= '\u0556')||(LA60_0 >= '\u0559' && LA60_0 <= '\u055F')||(LA60_0 >= '\u0561' && LA60_0 <= '\u0587')||(LA60_0 >= '\u0589' && LA60_0 <= '\u058A')||(LA60_0 >= '\u0591' && LA60_0 <= '\u05A1')||(LA60_0 >= '\u05A3' && LA60_0 <= '\u05B9')||(LA60_0 >= '\u05BB' && LA60_0 <= '\u05C4')||(LA60_0 >= '\u05D0' && LA60_0 <= '\u05EA')||(LA60_0 >= '\u05F0' && LA60_0 <= '\u05F4')||(LA60_0 >= '\u060C' && LA60_0 <= '\u0615')||LA60_0=='\u061B'||LA60_0=='\u061F'||(LA60_0 >= '\u0621' && LA60_0 <= '\u063A')||(LA60_0 >= '\u0640' && LA60_0 <= '\u0658')||(LA60_0 >= '\u0660' && LA60_0 <= '\u06DC')||(LA60_0 >= '\u06DE' && LA60_0 <= '\u070D')||(LA60_0 >= '\u0710' && LA60_0 <= '\u074A')||(LA60_0 >= '\u074D' && LA60_0 <= '\u074F')||(LA60_0 >= '\u0780' && LA60_0 <= '\u07B1')||(LA60_0 >= '\u0901' && LA60_0 <= '\u0939')||(LA60_0 >= '\u093C' && LA60_0 <= '\u094D')||(LA60_0 >= '\u0950' && LA60_0 <= '\u0954')||(LA60_0 >= '\u0958' && LA60_0 <= '\u0970')||(LA60_0 >= '\u0981' && LA60_0 <= '\u0983')||(LA60_0 >= '\u0985' && LA60_0 <= '\u098C')||(LA60_0 >= '\u098F' && LA60_0 <= '\u0990')||(LA60_0 >= '\u0993' && LA60_0 <= '\u09A8')||(LA60_0 >= '\u09AA' && LA60_0 <= '\u09B0')||LA60_0=='\u09B2'||(LA60_0 >= '\u09B6' && LA60_0 <= '\u09B9')||(LA60_0 >= '\u09BC' && LA60_0 <= '\u09C4')||(LA60_0 >= '\u09C7' && LA60_0 <= '\u09C8')||(LA60_0 >= '\u09CB' && LA60_0 <= '\u09CD')||LA60_0=='\u09D7'||(LA60_0 >= '\u09DC' && LA60_0 <= '\u09DD')||(LA60_0 >= '\u09DF' && LA60_0 <= '\u09E3')||(LA60_0 >= '\u09E6' && LA60_0 <= '\u09FA')||(LA60_0 >= '\u0A01' && LA60_0 <= '\u0A03')||(LA60_0 >= '\u0A05' && LA60_0 <= '\u0A0A')||(LA60_0 >= '\u0A0F' && LA60_0 <= '\u0A10')||(LA60_0 >= '\u0A13' && LA60_0 <= '\u0A28')||(LA60_0 >= '\u0A2A' && LA60_0 <= '\u0A30')||(LA60_0 >= '\u0A32' && LA60_0 <= '\u0A33')||(LA60_0 >= '\u0A35' && LA60_0 <= '\u0A36')||(LA60_0 >= '\u0A38' && LA60_0 <= '\u0A39')||LA60_0=='\u0A3C'||(LA60_0 >= '\u0A3E' && LA60_0 <= '\u0A42')||(LA60_0 >= '\u0A47' && LA60_0 <= '\u0A48')||(LA60_0 >= '\u0A4B' && LA60_0 <= '\u0A4D')||(LA60_0 >= '\u0A59' && LA60_0 <= '\u0A5C')||LA60_0=='\u0A5E'||(LA60_0 >= '\u0A66' && LA60_0 <= '\u0A74')||(LA60_0 >= '\u0A81' && LA60_0 <= '\u0A83')||(LA60_0 >= '\u0A85' && LA60_0 <= '\u0A8D')||(LA60_0 >= '\u0A8F' && LA60_0 <= '\u0A91')||(LA60_0 >= '\u0A93' && LA60_0 <= '\u0AA8')||(LA60_0 >= '\u0AAA' && LA60_0 <= '\u0AB0')||(LA60_0 >= '\u0AB2' && LA60_0 <= '\u0AB3')||(LA60_0 >= '\u0AB5' && LA60_0 <= '\u0AB9')||(LA60_0 >= '\u0ABC' && LA60_0 <= '\u0AC5')||(LA60_0 >= '\u0AC7' && LA60_0 <= '\u0AC9')||(LA60_0 >= '\u0ACB' && LA60_0 <= '\u0ACD')||LA60_0=='\u0AD0'||(LA60_0 >= '\u0AE0' && LA60_0 <= '\u0AE3')||(LA60_0 >= '\u0AE6' && LA60_0 <= '\u0AEF')||LA60_0=='\u0AF1'||(LA60_0 >= '\u0B01' && LA60_0 <= '\u0B03')||(LA60_0 >= '\u0B05' && LA60_0 <= '\u0B0C')||(LA60_0 >= '\u0B0F' && LA60_0 <= '\u0B10')||(LA60_0 >= '\u0B13' && LA60_0 <= '\u0B28')||(LA60_0 >= '\u0B2A' && LA60_0 <= '\u0B30')||(LA60_0 >= '\u0B32' && LA60_0 <= '\u0B33')||(LA60_0 >= '\u0B35' && LA60_0 <= '\u0B39')||(LA60_0 >= '\u0B3C' && LA60_0 <= '\u0B43')||(LA60_0 >= '\u0B47' && LA60_0 <= '\u0B48')||(LA60_0 >= '\u0B4B' && LA60_0 <= '\u0B4D')||(LA60_0 >= '\u0B56' && LA60_0 <= '\u0B57')||(LA60_0 >= '\u0B5C' && LA60_0 <= '\u0B5D')||(LA60_0 >= '\u0B5F' && LA60_0 <= '\u0B61')||(LA60_0 >= '\u0B66' && LA60_0 <= '\u0B71')||(LA60_0 >= '\u0B82' && LA60_0 <= '\u0B83')||(LA60_0 >= '\u0B85' && LA60_0 <= '\u0B8A')||(LA60_0 >= '\u0B8E' && LA60_0 <= '\u0B90')||(LA60_0 >= '\u0B92' && LA60_0 <= '\u0B95')||(LA60_0 >= '\u0B99' && LA60_0 <= '\u0B9A')||LA60_0=='\u0B9C'||(LA60_0 >= '\u0B9E' && LA60_0 <= '\u0B9F')||(LA60_0 >= '\u0BA3' && LA60_0 <= '\u0BA4')||(LA60_0 >= '\u0BA8' && LA60_0 <= '\u0BAA')||(LA60_0 >= '\u0BAE' && LA60_0 <= '\u0BB5')||(LA60_0 >= '\u0BB7' && LA60_0 <= '\u0BB9')||(LA60_0 >= '\u0BBE' && LA60_0 <= '\u0BC2')||(LA60_0 >= '\u0BC6' && LA60_0 <= '\u0BC8')||(LA60_0 >= '\u0BCA' && LA60_0 <= '\u0BCD')||LA60_0=='\u0BD7'||(LA60_0 >= '\u0BE7' && LA60_0 <= '\u0BFA')||(LA60_0 >= '\u0C01' && LA60_0 <= '\u0C03')||(LA60_0 >= '\u0C05' && LA60_0 <= '\u0C0C')||(LA60_0 >= '\u0C0E' && LA60_0 <= '\u0C10')||(LA60_0 >= '\u0C12' && LA60_0 <= '\u0C28')||(LA60_0 >= '\u0C2A' && LA60_0 <= '\u0C33')||(LA60_0 >= '\u0C35' && LA60_0 <= '\u0C39')||(LA60_0 >= '\u0C3E' && LA60_0 <= '\u0C44')||(LA60_0 >= '\u0C46' && LA60_0 <= '\u0C48')||(LA60_0 >= '\u0C4A' && LA60_0 <= '\u0C4D')||(LA60_0 >= '\u0C55' && LA60_0 <= '\u0C56')||(LA60_0 >= '\u0C60' && LA60_0 <= '\u0C61')||(LA60_0 >= '\u0C66' && LA60_0 <= '\u0C6F')||(LA60_0 >= '\u0C82' && LA60_0 <= '\u0C83')||(LA60_0 >= '\u0C85' && LA60_0 <= '\u0C8C')||(LA60_0 >= '\u0C8E' && LA60_0 <= '\u0C90')||(LA60_0 >= '\u0C92' && LA60_0 <= '\u0CA8')||(LA60_0 >= '\u0CAA' && LA60_0 <= '\u0CB3')||(LA60_0 >= '\u0CB5' && LA60_0 <= '\u0CB9')||(LA60_0 >= '\u0CBC' && LA60_0 <= '\u0CC4')||(LA60_0 >= '\u0CC6' && LA60_0 <= '\u0CC8')||(LA60_0 >= '\u0CCA' && LA60_0 <= '\u0CCD')||(LA60_0 >= '\u0CD5' && LA60_0 <= '\u0CD6')||LA60_0=='\u0CDE'||(LA60_0 >= '\u0CE0' && LA60_0 <= '\u0CE1')||(LA60_0 >= '\u0CE6' && LA60_0 <= '\u0CEF')||(LA60_0 >= '\u0D02' && LA60_0 <= '\u0D03')||(LA60_0 >= '\u0D05' && LA60_0 <= '\u0D0C')||(LA60_0 >= '\u0D0E' && LA60_0 <= '\u0D10')||(LA60_0 >= '\u0D12' && LA60_0 <= '\u0D28')||(LA60_0 >= '\u0D2A' && LA60_0 <= '\u0D39')||(LA60_0 >= '\u0D3E' && LA60_0 <= '\u0D43')||(LA60_0 >= '\u0D46' && LA60_0 <= '\u0D48')||(LA60_0 >= '\u0D4A' && LA60_0 <= '\u0D4D')||LA60_0=='\u0D57'||(LA60_0 >= '\u0D60' && LA60_0 <= '\u0D61')||(LA60_0 >= '\u0D66' && LA60_0 <= '\u0D6F')||(LA60_0 >= '\u0D82' && LA60_0 <= '\u0D83')||(LA60_0 >= '\u0D85' && LA60_0 <= '\u0D96')||(LA60_0 >= '\u0D9A' && LA60_0 <= '\u0DB1')||(LA60_0 >= '\u0DB3' && LA60_0 <= '\u0DBB')||LA60_0=='\u0DBD'||(LA60_0 >= '\u0DC0' && LA60_0 <= '\u0DC6')||LA60_0=='\u0DCA'||(LA60_0 >= '\u0DCF' && LA60_0 <= '\u0DD4')||LA60_0=='\u0DD6'||(LA60_0 >= '\u0DD8' && LA60_0 <= '\u0DDF')||(LA60_0 >= '\u0DF2' && LA60_0 <= '\u0DF4')||(LA60_0 >= '\u0E01' && LA60_0 <= '\u0E3A')||(LA60_0 >= '\u0E3F' && LA60_0 <= '\u0E5B')||(LA60_0 >= '\u0E81' && LA60_0 <= '\u0E82')||LA60_0=='\u0E84'||(LA60_0 >= '\u0E87' && LA60_0 <= '\u0E88')||LA60_0=='\u0E8A'||LA60_0=='\u0E8D'||(LA60_0 >= '\u0E94' && LA60_0 <= '\u0E97')||(LA60_0 >= '\u0E99' && LA60_0 <= '\u0E9F')||(LA60_0 >= '\u0EA1' && LA60_0 <= '\u0EA3')||LA60_0=='\u0EA5'||LA60_0=='\u0EA7'||(LA60_0 >= '\u0EAA' && LA60_0 <= '\u0EAB')||(LA60_0 >= '\u0EAD' && LA60_0 <= '\u0EB9')||(LA60_0 >= '\u0EBB' && LA60_0 <= '\u0EBD')||(LA60_0 >= '\u0EC0' && LA60_0 <= '\u0EC4')||LA60_0=='\u0EC6'||(LA60_0 >= '\u0EC8' && LA60_0 <= '\u0ECD')||(LA60_0 >= '\u0ED0' && LA60_0 <= '\u0ED9')||(LA60_0 >= '\u0EDC' && LA60_0 <= '\u0EDD')||(LA60_0 >= '\u0F00' && LA60_0 <= '\u0F39')||(LA60_0 >= '\u0F3E' && LA60_0 <= '\u0F47')||(LA60_0 >= '\u0F49' && LA60_0 <= '\u0F6A')||(LA60_0 >= '\u0F71' && LA60_0 <= '\u0F8B')||(LA60_0 >= '\u0F90' && LA60_0 <= '\u0F97')||(LA60_0 >= '\u0F99' && LA60_0 <= '\u0FBC')||(LA60_0 >= '\u0FBE' && LA60_0 <= '\u0FCC')||LA60_0=='\u0FCF'||(LA60_0 >= '\u1000' && LA60_0 <= '\u1021')||(LA60_0 >= '\u1023' && LA60_0 <= '\u1027')||(LA60_0 >= '\u1029' && LA60_0 <= '\u102A')||(LA60_0 >= '\u102C' && LA60_0 <= '\u1032')||(LA60_0 >= '\u1036' && LA60_0 <= '\u1039')||(LA60_0 >= '\u1040' && LA60_0 <= '\u1059')||(LA60_0 >= '\u10A0' && LA60_0 <= '\u10C5')||(LA60_0 >= '\u10D0' && LA60_0 <= '\u10F8')||LA60_0=='\u10FB'||(LA60_0 >= '\u1100' && LA60_0 <= '\u1159')||(LA60_0 >= '\u115F' && LA60_0 <= '\u11A2')||(LA60_0 >= '\u11A8' && LA60_0 <= '\u11F9')||(LA60_0 >= '\u1200' && LA60_0 <= '\u1206')||(LA60_0 >= '\u1208' && LA60_0 <= '\u1246')||LA60_0=='\u1248'||(LA60_0 >= '\u124A' && LA60_0 <= '\u124D')||(LA60_0 >= '\u1250' && LA60_0 <= '\u1256')||LA60_0=='\u1258'||(LA60_0 >= '\u125A' && LA60_0 <= '\u125D')||(LA60_0 >= '\u1260' && LA60_0 <= '\u1286')||LA60_0=='\u1288'||(LA60_0 >= '\u128A' && LA60_0 <= '\u128D')||(LA60_0 >= '\u1290' && LA60_0 <= '\u12AE')||LA60_0=='\u12B0'||(LA60_0 >= '\u12B2' && LA60_0 <= '\u12B5')||(LA60_0 >= '\u12B8' && LA60_0 <= '\u12BE')||LA60_0=='\u12C0'||(LA60_0 >= '\u12C2' && LA60_0 <= '\u12C5')||(LA60_0 >= '\u12C8' && LA60_0 <= '\u12CE')||(LA60_0 >= '\u12D0' && LA60_0 <= '\u12D6')||(LA60_0 >= '\u12D8' && LA60_0 <= '\u12EE')||(LA60_0 >= '\u12F0' && LA60_0 <= '\u130E')||LA60_0=='\u1310'||(LA60_0 >= '\u1312' && LA60_0 <= '\u1315')||(LA60_0 >= '\u1318' && LA60_0 <= '\u131E')||(LA60_0 >= '\u1320' && LA60_0 <= '\u1346')||(LA60_0 >= '\u1348' && LA60_0 <= '\u135A')||(LA60_0 >= '\u1361' && LA60_0 <= '\u137C')||(LA60_0 >= '\u13A0' && LA60_0 <= '\u13F4')||(LA60_0 >= '\u1401' && LA60_0 <= '\u1676')||(LA60_0 >= '\u1681' && LA60_0 <= '\u169A')||(LA60_0 >= '\u16A0' && LA60_0 <= '\u16F0')||(LA60_0 >= '\u1700' && LA60_0 <= '\u170C')||(LA60_0 >= '\u170E' && LA60_0 <= '\u1714')||(LA60_0 >= '\u1720' && LA60_0 <= '\u1736')||(LA60_0 >= '\u1740' && LA60_0 <= '\u1753')||(LA60_0 >= '\u1760' && LA60_0 <= '\u176C')||(LA60_0 >= '\u176E' && LA60_0 <= '\u1770')||(LA60_0 >= '\u1772' && LA60_0 <= '\u1773')||(LA60_0 >= '\u1780' && LA60_0 <= '\u17B3')||(LA60_0 >= '\u17B6' && LA60_0 <= '\u17DD')||(LA60_0 >= '\u17E0' && LA60_0 <= '\u17E9')||(LA60_0 >= '\u17F0' && LA60_0 <= '\u17F9')||(LA60_0 >= '\u1800' && LA60_0 <= '\u180D')||(LA60_0 >= '\u1810' && LA60_0 <= '\u1819')||(LA60_0 >= '\u1820' && LA60_0 <= '\u1877')||(LA60_0 >= '\u1880' && LA60_0 <= '\u18A9')||(LA60_0 >= '\u1900' && LA60_0 <= '\u191C')||(LA60_0 >= '\u1920' && LA60_0 <= '\u192B')||(LA60_0 >= '\u1930' && LA60_0 <= '\u193B')||LA60_0=='\u1940'||(LA60_0 >= '\u1944' && LA60_0 <= '\u196D')||(LA60_0 >= '\u1970' && LA60_0 <= '\u1974')||(LA60_0 >= '\u19E0' && LA60_0 <= '\u19FF')||(LA60_0 >= '\u1D00' && LA60_0 <= '\u1D6B')||(LA60_0 >= '\u1E00' && LA60_0 <= '\u1E9B')||(LA60_0 >= '\u1EA0' && LA60_0 <= '\u1EF9')||(LA60_0 >= '\u1F00' && LA60_0 <= '\u1F15')||(LA60_0 >= '\u1F18' && LA60_0 <= '\u1F1D')||(LA60_0 >= '\u1F20' && LA60_0 <= '\u1F45')||(LA60_0 >= '\u1F48' && LA60_0 <= '\u1F4D')||(LA60_0 >= '\u1F50' && LA60_0 <= '\u1F57')||LA60_0=='\u1F59'||LA60_0=='\u1F5B'||LA60_0=='\u1F5D'||(LA60_0 >= '\u1F5F' && LA60_0 <= '\u1F7D')||(LA60_0 >= '\u1F80' && LA60_0 <= '\u1FB4')||(LA60_0 >= '\u1FB6' && LA60_0 <= '\u1FBC')||LA60_0=='\u1FBE'||(LA60_0 >= '\u1FC2' && LA60_0 <= '\u1FC4')||(LA60_0 >= '\u1FC6' && LA60_0 <= '\u1FCC')||(LA60_0 >= '\u1FD0' && LA60_0 <= '\u1FD3')||(LA60_0 >= '\u1FD6' && LA60_0 <= '\u1FDB')||(LA60_0 >= '\u1FE0' && LA60_0 <= '\u1FEC')||(LA60_0 >= '\u1FF2' && LA60_0 <= '\u1FF4')||(LA60_0 >= '\u1FF6' && LA60_0 <= '\u1FFC')||(LA60_0 >= '\u2010' && LA60_0 <= '\u2017')||(LA60_0 >= '\u2020' && LA60_0 <= '\u2027')||(LA60_0 >= '\u2030' && LA60_0 <= '\u2038')||(LA60_0 >= '\u203B' && LA60_0 <= '\u2044')||(LA60_0 >= '\u2047' && LA60_0 <= '\u2054')||LA60_0=='\u2057'||(LA60_0 >= '\u2070' && LA60_0 <= '\u2071')||(LA60_0 >= '\u2074' && LA60_0 <= '\u207C')||(LA60_0 >= '\u207F' && LA60_0 <= '\u208C')||(LA60_0 >= '\u20A0' && LA60_0 <= '\u20B1')||(LA60_0 >= '\u20D0' && LA60_0 <= '\u20EA')||(LA60_0 >= '\u2100' && LA60_0 <= '\u213B')||(LA60_0 >= '\u213D' && LA60_0 <= '\u214B')||(LA60_0 >= '\u2153' && LA60_0 <= '\u2183')||(LA60_0 >= '\u2190' && LA60_0 <= '\u2328')||(LA60_0 >= '\u232B' && LA60_0 <= '\u23B3')||(LA60_0 >= '\u23B6' && LA60_0 <= '\u23D0')||(LA60_0 >= '\u2400' && LA60_0 <= '\u2426')||(LA60_0 >= '\u2440' && LA60_0 <= '\u244A')||(LA60_0 >= '\u2460' && LA60_0 <= '\u2617')||(LA60_0 >= '\u2619' && LA60_0 <= '\u267D')||(LA60_0 >= '\u2680' && LA60_0 <= '\u2691')||(LA60_0 >= '\u26A0' && LA60_0 <= '\u26A1')||(LA60_0 >= '\u2701' && LA60_0 <= '\u2704')||(LA60_0 >= '\u2706' && LA60_0 <= '\u2709')||(LA60_0 >= '\u270C' && LA60_0 <= '\u2727')||(LA60_0 >= '\u2729' && LA60_0 <= '\u274B')||LA60_0=='\u274D'||(LA60_0 >= '\u274F' && LA60_0 <= '\u2752')||LA60_0=='\u2756'||(LA60_0 >= '\u2758' && LA60_0 <= '\u275E')||(LA60_0 >= '\u2761' && LA60_0 <= '\u2767')||(LA60_0 >= '\u2776' && LA60_0 <= '\u2794')||(LA60_0 >= '\u2798' && LA60_0 <= '\u27AF')||(LA60_0 >= '\u27B1' && LA60_0 <= '\u27BE')||(LA60_0 >= '\u27D0' && LA60_0 <= '\u27E5')||(LA60_0 >= '\u27F0' && LA60_0 <= '\u2982')||(LA60_0 >= '\u2999' && LA60_0 <= '\u29D7')||(LA60_0 >= '\u29DC' && LA60_0 <= '\u29FB')||(LA60_0 >= '\u29FE' && LA60_0 <= '\u2B0D')||(LA60_0 >= '\u2E80' && LA60_0 <= '\u2E99')||(LA60_0 >= '\u2E9B' && LA60_0 <= '\u2EF3')||(LA60_0 >= '\u2F00' && LA60_0 <= '\u2FD5')||(LA60_0 >= '\u2FF0' && LA60_0 <= '\u2FFB')||(LA60_0 >= '\u3001' && LA60_0 <= '\u3007')||(LA60_0 >= '\u3012' && LA60_0 <= '\u3013')||LA60_0=='\u301C'||(LA60_0 >= '\u3020' && LA60_0 <= '\u303F')||(LA60_0 >= '\u3041' && LA60_0 <= '\u3096')||(LA60_0 >= '\u3099' && LA60_0 <= '\u309A')||(LA60_0 >= '\u309D' && LA60_0 <= '\u30FF')||(LA60_0 >= '\u3105' && LA60_0 <= '\u312C')||(LA60_0 >= '\u3131' && LA60_0 <= '\u318E')||(LA60_0 >= '\u3190' && LA60_0 <= '\u31B7')||(LA60_0 >= '\u31F0' && LA60_0 <= '\u321E')||(LA60_0 >= '\u3220' && LA60_0 <= '\u3243')||(LA60_0 >= '\u3250' && LA60_0 <= '\u327D')||(LA60_0 >= '\u327F' && LA60_0 <= '\u32FE')||(LA60_0 >= '\u3300' && LA60_0 <= '\u4DB5')||(LA60_0 >= '\u4DC0' && LA60_0 <= '\u9FA5')||(LA60_0 >= '\uA000' && LA60_0 <= '\uA48C')||(LA60_0 >= '\uA490' && LA60_0 <= '\uA4C6')||(LA60_0 >= '\uAC00' && LA60_0 <= '\uD7A3')||(LA60_0 >= '\uF900' && LA60_0 <= '\uFA2D')||(LA60_0 >= '\uFA30' && LA60_0 <= '\uFA6A')||(LA60_0 >= '\uFB00' && LA60_0 <= '\uFB06')||(LA60_0 >= '\uFB13' && LA60_0 <= '\uFB17')||(LA60_0 >= '\uFB1D' && LA60_0 <= '\uFB36')||(LA60_0 >= '\uFB38' && LA60_0 <= '\uFB3C')||LA60_0=='\uFB3E'||(LA60_0 >= '\uFB40' && LA60_0 <= '\uFB41')||(LA60_0 >= '\uFB43' && LA60_0 <= '\uFB44')||(LA60_0 >= '\uFB46' && LA60_0 <= '\uFBB1')||(LA60_0 >= '\uFBD3' && LA60_0 <= '\uFD3D')||(LA60_0 >= '\uFD50' && LA60_0 <= '\uFD8F')||(LA60_0 >= '\uFD92' && LA60_0 <= '\uFDC7')||(LA60_0 >= '\uFDF0' && LA60_0 <= '\uFDFD')||(LA60_0 >= '\uFE00' && LA60_0 <= '\uFE0F')||(LA60_0 >= '\uFE20' && LA60_0 <= '\uFE23')||(LA60_0 >= '\uFE30' && LA60_0 <= '\uFE34')||(LA60_0 >= '\uFE45' && LA60_0 <= '\uFE46')||(LA60_0 >= '\uFE49' && LA60_0 <= '\uFE52')||(LA60_0 >= '\uFE54' && LA60_0 <= '\uFE58')||(LA60_0 >= '\uFE5F' && LA60_0 <= '\uFE66')||(LA60_0 >= '\uFE68' && LA60_0 <= '\uFE6B')||(LA60_0 >= '\uFE70' && LA60_0 <= '\uFE74')||(LA60_0 >= '\uFE76' && LA60_0 <= '\uFEFC')||(LA60_0 >= '\uFF01' && LA60_0 <= '\uFF07')||(LA60_0 >= '\uFF0A' && LA60_0 <= '\uFF3A')||LA60_0=='\uFF3C'||LA60_0=='\uFF3F'||(LA60_0 >= '\uFF41' && LA60_0 <= '\uFF5A')||LA60_0=='\uFF5C'||LA60_0=='\uFF5E'||LA60_0=='\uFF61'||(LA60_0 >= '\uFF64' && LA60_0 <= '\uFFBE')||(LA60_0 >= '\uFFC2' && LA60_0 <= '\uFFC7')||(LA60_0 >= '\uFFCA' && LA60_0 <= '\uFFCF')||(LA60_0 >= '\uFFD2' && LA60_0 <= '\uFFD7')||(LA60_0 >= '\uFFDA' && LA60_0 <= '\uFFDC')||(LA60_0 >= '\uFFE0' && LA60_0 <= '\uFFE2')||(LA60_0 >= '\uFFE4' && LA60_0 <= '\uFFE6')||(LA60_0 >= '\uFFE8' && LA60_0 <= '\uFFEE')) ) { + alt60=2; + } + else if ( (LA60_0=='*') ) { + alt60=3; + } + else if ( (LA60_0=='?') ) { + alt60=4; + } + + switch (alt60) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1542:17: F_ESC + { + mF_ESC(); if (state.failed) return; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1543:19: IN_WORD + { + mIN_WORD(); if (state.failed) return; + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1544:19: STAR + { + mSTAR(); if (state.failed) return; + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1545:19: QUESTION_MARK + { + mQUESTION_MARK(); if (state.failed) return; + + } + break; + + default : + break loop60; + } + } + + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "FTSWILD" + + // $ANTLR start "F_ESC" + public final void mF_ESC() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1552:9: ( '\\\\' ( 'u' F_HEX F_HEX F_HEX F_HEX | . ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1553:9: '\\\\' ( 'u' F_HEX F_HEX F_HEX F_HEX | . ) + { + match('\\'); if (state.failed) return; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1554:9: ( 'u' F_HEX F_HEX F_HEX F_HEX | . ) + int alt61=2; + int LA61_0 = input.LA(1); + if ( (LA61_0=='u') ) { + int LA61_1 = input.LA(2); + if ( ((LA61_1 >= '0' && LA61_1 <= '9')||(LA61_1 >= 'A' && LA61_1 <= 'F')||(LA61_1 >= 'a' && LA61_1 <= 'f')) ) { + alt61=1; + } + + else { + alt61=2; + } + + } + else if ( ((LA61_0 >= '\u0000' && LA61_0 <= 't')||(LA61_0 >= 'v' && LA61_0 <= '\uFFFF')) ) { + alt61=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + NoViableAltException nvae = + new NoViableAltException("", 61, 0, input); + throw nvae; + } + + switch (alt61) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1556:17: 'u' F_HEX F_HEX F_HEX F_HEX + { + match('u'); if (state.failed) return; + mF_HEX(); if (state.failed) return; + + mF_HEX(); if (state.failed) return; + + mF_HEX(); if (state.failed) return; + + mF_HEX(); if (state.failed) return; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1558:19: . + { + matchAny(); if (state.failed) return; + } + break; + + } + + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "F_ESC" + + // $ANTLR start "F_HEX" + public final void mF_HEX() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1564:9: ( '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( (input.LA(1) >= '0' && input.LA(1) <= '9')||(input.LA(1) >= 'A' && input.LA(1) <= 'F')||(input.LA(1) >= 'a' && input.LA(1) <= 'f') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "F_HEX" + + // $ANTLR start "START_WORD" + public final void mSTART_WORD() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1572:9: ( '\\u0024' | '\\u0030' .. '\\u0039' | '\\u0041' .. '\\u005a' | '\\u0061' .. '\\u007a' | '\\u00a2' .. '\\u00a7' | '\\u00a9' .. '\\u00aa' | '\\u00ae' | '\\u00b0' | '\\u00b2' .. '\\u00b3' | '\\u00b5' .. '\\u00b6' | '\\u00b9' .. '\\u00ba' | '\\u00bc' .. '\\u00be' | '\\u00c0' .. '\\u00d6' | '\\u00d8' .. '\\u00f6' | '\\u00f8' .. '\\u0236' | '\\u0250' .. '\\u02c1' | '\\u02c6' .. '\\u02d1' | '\\u02e0' .. '\\u02e4' | '\\u02ee' | '\\u0300' .. '\\u0357' | '\\u035d' .. '\\u036f' | '\\u037a' .. '\\u037a' | '\\u0386' | '\\u0388' .. '\\u038a' | '\\u038c' .. '\\u038c' | '\\u038e' .. '\\u03a1' | '\\u03a3' .. '\\u03ce' | '\\u03d0' .. '\\u03f5' | '\\u03f7' .. '\\u03fb' | '\\u0400' .. '\\u0486' | '\\u0488' .. '\\u04ce' | '\\u04d0' .. '\\u04f5' | '\\u04f8' .. '\\u04f9' | '\\u0500' .. '\\u050f' | '\\u0531' .. '\\u0556' | '\\u0559' | '\\u0561' .. '\\u0587' | '\\u0591' .. '\\u05a1' | '\\u05a3' .. '\\u05b9' | '\\u05bb' .. '\\u05bd' | '\\u05bf' | '\\u05c1' .. '\\u05c2' | '\\u05c4' .. '\\u05c4' | '\\u05d0' .. '\\u05ea' | '\\u05f0' .. '\\u05f2' | '\\u060e' .. '\\u0615' | '\\u0621' .. '\\u063a' | '\\u0640' .. '\\u0658' | '\\u0660' .. '\\u0669' | '\\u066e' .. '\\u06d3' | '\\u06d5' .. '\\u06dc' | '\\u06de' .. '\\u06ff' | '\\u0710' .. '\\u074a' | '\\u074d' .. '\\u074f' | '\\u0780' .. '\\u07b1' | '\\u0901' .. '\\u0939' | '\\u093c' .. '\\u094d' | '\\u0950' .. '\\u0954' | '\\u0958' .. '\\u0963' | '\\u0966' .. '\\u096f' | '\\u0981' .. '\\u0983' | '\\u0985' .. '\\u098c' | '\\u098f' .. '\\u0990' | '\\u0993' .. '\\u09a8' | '\\u09aa' .. '\\u09b0' | '\\u09b2' .. '\\u09b2' | '\\u09b6' .. '\\u09b9' | '\\u09bc' .. '\\u09c4' | '\\u09c7' .. '\\u09c8' | '\\u09cb' .. '\\u09cd' | '\\u09d7' .. '\\u09d7' | '\\u09dc' .. '\\u09dd' | '\\u09df' .. '\\u09e3' | '\\u09e6' .. '\\u09fa' | '\\u0a01' .. '\\u0a03' | '\\u0a05' .. '\\u0a0a' | '\\u0a0f' .. '\\u0a10' | '\\u0a13' .. '\\u0a28' | '\\u0a2a' .. '\\u0a30' | '\\u0a32' .. '\\u0a33' | '\\u0a35' .. '\\u0a36' | '\\u0a38' .. '\\u0a39' | '\\u0a3c' .. '\\u0a3c' | '\\u0a3e' .. '\\u0a42' | '\\u0a47' .. '\\u0a48' | '\\u0a4b' .. '\\u0a4d' | '\\u0a59' .. '\\u0a5c' | '\\u0a5e' .. '\\u0a5e' | '\\u0a66' .. '\\u0a74' | '\\u0a81' .. '\\u0a83' | '\\u0a85' .. '\\u0a8d' | '\\u0a8f' .. '\\u0a91' | '\\u0a93' .. '\\u0aa8' | '\\u0aaa' .. '\\u0ab0' | '\\u0ab2' .. '\\u0ab3' | '\\u0ab5' .. '\\u0ab9' | '\\u0abc' .. '\\u0ac5' | '\\u0ac7' .. '\\u0ac9' | '\\u0acb' .. '\\u0acd' | '\\u0ad0' .. '\\u0ad0' | '\\u0ae0' .. '\\u0ae3' | '\\u0ae6' .. '\\u0aef' | '\\u0af1' .. '\\u0af1' | '\\u0b01' .. '\\u0b03' | '\\u0b05' .. '\\u0b0c' | '\\u0b0f' .. '\\u0b10' | '\\u0b13' .. '\\u0b28' | '\\u0b2a' .. '\\u0b30' | '\\u0b32' .. '\\u0b33' | '\\u0b35' .. '\\u0b39' | '\\u0b3c' .. '\\u0b43' | '\\u0b47' .. '\\u0b48' | '\\u0b4b' .. '\\u0b4d' | '\\u0b56' .. '\\u0b57' | '\\u0b5c' .. '\\u0b5d' | '\\u0b5f' .. '\\u0b61' | '\\u0b66' .. '\\u0b71' | '\\u0b82' .. '\\u0b83' | '\\u0b85' .. '\\u0b8a' | '\\u0b8e' .. '\\u0b90' | '\\u0b92' .. '\\u0b95' | '\\u0b99' .. '\\u0b9a' | '\\u0b9c' .. '\\u0b9c' | '\\u0b9e' .. '\\u0b9f' | '\\u0ba3' .. '\\u0ba4' | '\\u0ba8' .. '\\u0baa' | '\\u0bae' .. '\\u0bb5' | '\\u0bb7' .. '\\u0bb9' | '\\u0bbe' .. '\\u0bc2' | '\\u0bc6' .. '\\u0bc8' | '\\u0bca' .. '\\u0bcd' | '\\u0bd7' .. '\\u0bd7' | '\\u0be7' .. '\\u0bfa' | '\\u0c01' .. '\\u0c03' | '\\u0c05' .. '\\u0c0c' | '\\u0c0e' .. '\\u0c10' | '\\u0c12' .. '\\u0c28' | '\\u0c2a' .. '\\u0c33' | '\\u0c35' .. '\\u0c39' | '\\u0c3e' .. '\\u0c44' | '\\u0c46' .. '\\u0c48' | '\\u0c4a' .. '\\u0c4d' | '\\u0c55' .. '\\u0c56' | '\\u0c60' .. '\\u0c61' | '\\u0c66' .. '\\u0c6f' | '\\u0c82' .. '\\u0c83' | '\\u0c85' .. '\\u0c8c' | '\\u0c8e' .. '\\u0c90' | '\\u0c92' .. '\\u0ca8' | '\\u0caa' .. '\\u0cb3' | '\\u0cb5' .. '\\u0cb9' | '\\u0cbc' .. '\\u0cc4' | '\\u0cc6' .. '\\u0cc8' | '\\u0cca' .. '\\u0ccd' | '\\u0cd5' .. '\\u0cd6' | '\\u0cde' .. '\\u0cde' | '\\u0ce0' .. '\\u0ce1' | '\\u0ce6' .. '\\u0cef' | '\\u0d02' .. '\\u0d03' | '\\u0d05' .. '\\u0d0c' | '\\u0d0e' .. '\\u0d10' | '\\u0d12' .. '\\u0d28' | '\\u0d2a' .. '\\u0d39' | '\\u0d3e' .. '\\u0d43' | '\\u0d46' .. '\\u0d48' | '\\u0d4a' .. '\\u0d4d' | '\\u0d57' .. '\\u0d57' | '\\u0d60' .. '\\u0d61' | '\\u0d66' .. '\\u0d6f' | '\\u0d82' .. '\\u0d83' | '\\u0d85' .. '\\u0d96' | '\\u0d9a' .. '\\u0db1' | '\\u0db3' .. '\\u0dbb' | '\\u0dbd' .. '\\u0dbd' | '\\u0dc0' .. '\\u0dc6' | '\\u0dca' .. '\\u0dca' | '\\u0dcf' .. '\\u0dd4' | '\\u0dd6' .. '\\u0dd6' | '\\u0dd8' .. '\\u0ddf' | '\\u0df2' .. '\\u0df3' | '\\u0e01' .. '\\u0e3a' | '\\u0e3f' .. '\\u0e4e' | '\\u0e50' .. '\\u0e59' | '\\u0e81' .. '\\u0e82' | '\\u0e84' .. '\\u0e84' | '\\u0e87' .. '\\u0e88' | '\\u0e8a' .. '\\u0e8a' | '\\u0e8d' .. '\\u0e8d' | '\\u0e94' .. '\\u0e97' | '\\u0e99' .. '\\u0e9f' | '\\u0ea1' .. '\\u0ea3' | '\\u0ea5' .. '\\u0ea5' | '\\u0ea7' .. '\\u0ea7' | '\\u0eaa' .. '\\u0eab' | '\\u0ead' .. '\\u0eb9' | '\\u0ebb' .. '\\u0ebd' | '\\u0ec0' .. '\\u0ec4' | '\\u0ec6' .. '\\u0ec6' | '\\u0ec8' .. '\\u0ecd' | '\\u0ed0' .. '\\u0ed9' | '\\u0edc' .. '\\u0edd' | '\\u0f00' .. '\\u0f03' | '\\u0f13' .. '\\u0f39' | '\\u0f3e' .. '\\u0f47' | '\\u0f49' .. '\\u0f6a' | '\\u0f71' .. '\\u0f84' | '\\u0f86' .. '\\u0f8b' | '\\u0f90' .. '\\u0f97' | '\\u0f99' .. '\\u0fbc' | '\\u0fbe' .. '\\u0fcc' | '\\u0fcf' .. '\\u0fcf' | '\\u1000' .. '\\u1021' | '\\u1023' .. '\\u1027' | '\\u1029' .. '\\u102a' | '\\u102c' .. '\\u1032' | '\\u1036' .. '\\u1039' | '\\u1040' .. '\\u1049' | '\\u1050' .. '\\u1059' | '\\u10a0' .. '\\u10c5' | '\\u10d0' .. '\\u10f8' | '\\u1100' .. '\\u1159' | '\\u115f' .. '\\u11a2' | '\\u11a8' .. '\\u11f9' | '\\u1200' .. '\\u1206' | '\\u1208' .. '\\u1246' | '\\u1248' .. '\\u1248' | '\\u124a' .. '\\u124d' | '\\u1250' .. '\\u1256' | '\\u1258' .. '\\u1258' | '\\u125a' .. '\\u125d' | '\\u1260' .. '\\u1286' | '\\u1288' .. '\\u1288' | '\\u128a' .. '\\u128d' | '\\u1290' .. '\\u12ae' | '\\u12b0' .. '\\u12b0' | '\\u12b2' .. '\\u12b5' | '\\u12b8' .. '\\u12be' | '\\u12c0' .. '\\u12c0' | '\\u12c2' .. '\\u12c5' | '\\u12c8' .. '\\u12ce' | '\\u12d0' .. '\\u12d6' | '\\u12d8' .. '\\u12ee' | '\\u12f0' .. '\\u130e' | '\\u1310' .. '\\u1310' | '\\u1312' .. '\\u1315' | '\\u1318' .. '\\u131e' | '\\u1320' .. '\\u1346' | '\\u1348' .. '\\u135a' | '\\u1369' .. '\\u137c' | '\\u13a0' .. '\\u13f4' | '\\u1401' .. '\\u166c' | '\\u166f' .. '\\u1676' | '\\u1681' .. '\\u169a' | '\\u16a0' .. '\\u16ea' | '\\u16ee' .. '\\u16f0' | '\\u1700' .. '\\u170c' | '\\u170e' .. '\\u1714' | '\\u1720' .. '\\u1734' | '\\u1740' .. '\\u1753' | '\\u1760' .. '\\u176c' | '\\u176e' .. '\\u1770' | '\\u1772' .. '\\u1773' | '\\u1780' .. '\\u17b3' | '\\u17b6' .. '\\u17d3' | '\\u17d7' | '\\u17db' .. '\\u17dd' | '\\u17e0' .. '\\u17e9' | '\\u17f0' .. '\\u17f9' | '\\u180b' .. '\\u180d' | '\\u1810' .. '\\u1819' | '\\u1820' .. '\\u1877' | '\\u1880' .. '\\u18a9' | '\\u1900' .. '\\u191c' | '\\u1920' .. '\\u192b' | '\\u1930' .. '\\u193b' | '\\u1940' .. '\\u1940' | '\\u1946' .. '\\u196d' | '\\u1970' .. '\\u1974' | '\\u19e0' .. '\\u19ff' | '\\u1d00' .. '\\u1d6b' | '\\u1e00' .. '\\u1e9b' | '\\u1ea0' .. '\\u1ef9' | '\\u1f00' .. '\\u1f15' | '\\u1f18' .. '\\u1f1d' | '\\u1f20' .. '\\u1f45' | '\\u1f48' .. '\\u1f4d' | '\\u1f50' .. '\\u1f57' | '\\u1f59' .. '\\u1f59' | '\\u1f5b' .. '\\u1f5b' | '\\u1f5d' .. '\\u1f5d' | '\\u1f5f' .. '\\u1f7d' | '\\u1f80' .. '\\u1fb4' | '\\u1fb6' .. '\\u1fbc' | '\\u1fbe' | '\\u1fc2' .. '\\u1fc4' | '\\u1fc6' .. '\\u1fcc' | '\\u1fd0' .. '\\u1fd3' | '\\u1fd6' .. '\\u1fdb' | '\\u1fe0' .. '\\u1fec' | '\\u1ff2' .. '\\u1ff4' | '\\u1ff6' .. '\\u1ffc' | '\\u2070' .. '\\u2071' | '\\u2074' .. '\\u2079' | '\\u207f' .. '\\u2089' | '\\u20a0' .. '\\u20b1' | '\\u20d0' .. '\\u20ea' | '\\u2100' .. '\\u213b' | '\\u213d' .. '\\u213f' | '\\u2145' .. '\\u214a' | '\\u2153' .. '\\u2183' | '\\u2195' .. '\\u2199' | '\\u219c' .. '\\u219f' | '\\u21a1' .. '\\u21a2' | '\\u21a4' .. '\\u21a5' | '\\u21a7' .. '\\u21ad' | '\\u21af' .. '\\u21cd' | '\\u21d0' .. '\\u21d1' | '\\u21d3' | '\\u21d5' .. '\\u21f3' | '\\u2300' .. '\\u2307' | '\\u230c' .. '\\u231f' | '\\u2322' .. '\\u2328' | '\\u232b' .. '\\u237b' | '\\u237d' .. '\\u239a' | '\\u23b7' .. '\\u23d0' | '\\u2400' .. '\\u2426' | '\\u2440' .. '\\u244a' | '\\u2460' .. '\\u25b6' | '\\u25b8' .. '\\u25c0' | '\\u25c2' .. '\\u25f7' | '\\u2600' .. '\\u2617' | '\\u2619' .. '\\u266e' | '\\u2670' .. '\\u267d' | '\\u2680' .. '\\u2691' | '\\u26a0' .. '\\u26a1' | '\\u2701' .. '\\u2704' | '\\u2706' .. '\\u2709' | '\\u270c' .. '\\u2727' | '\\u2729' .. '\\u274b' | '\\u274d' .. '\\u274d' | '\\u274f' .. '\\u2752' | '\\u2756' .. '\\u2756' | '\\u2758' .. '\\u275e' | '\\u2761' .. '\\u2767' | '\\u2776' .. '\\u2794' | '\\u2798' .. '\\u27af' | '\\u27b1' .. '\\u27be' | '\\u2800' .. '\\u28ff' | '\\u2b00' .. '\\u2b0d' | '\\u2e80' .. '\\u2e99' | '\\u2e9b' .. '\\u2ef3' | '\\u2f00' .. '\\u2fd5' | '\\u2ff0' .. '\\u2ffb' | '\\u3004' .. '\\u3007' | '\\u3012' .. '\\u3013' | '\\u3020' .. '\\u302f' | '\\u3031' .. '\\u303c' | '\\u303e' .. '\\u303f' | '\\u3041' .. '\\u3096' | '\\u3099' .. '\\u309a' | '\\u309d' .. '\\u309f' | '\\u30a1' .. '\\u30fa' | '\\u30fc' .. '\\u30ff' | '\\u3105' .. '\\u312c' | '\\u3131' .. '\\u318e' | '\\u3190' .. '\\u31b7' | '\\u31f0' .. '\\u321e' | '\\u3220' .. '\\u3243' | '\\u3250' .. '\\u327d' | '\\u327f' .. '\\u32fe' | '\\u3300' .. '\\u4db5' | '\\u4dc0' .. '\\u9fa5' | '\\ua000' .. '\\ua48c' | '\\ua490' .. '\\ua4c6' | '\\uac00' .. '\\ud7a3' | '\\uf900' .. '\\ufa2d' | '\\ufa30' .. '\\ufa6a' | '\\ufb00' .. '\\ufb06' | '\\ufb13' .. '\\ufb17' | '\\ufb1d' .. '\\ufb28' | '\\ufb2a' .. '\\ufb36' | '\\ufb38' .. '\\ufb3c' | '\\ufb3e' .. '\\ufb3e' | '\\ufb40' .. '\\ufb41' | '\\ufb43' .. '\\ufb44' | '\\ufb46' .. '\\ufbb1' | '\\ufbd3' .. '\\ufd3d' | '\\ufd50' .. '\\ufd8f' | '\\ufd92' .. '\\ufdc7' | '\\ufdf0' .. '\\ufdfd' | '\\ufe00' .. '\\ufe0f' | '\\ufe20' .. '\\ufe23' | '\\ufe69' | '\\ufe70' .. '\\ufe74' | '\\ufe76' .. '\\ufefc' | '\\uff04' | '\\uff10' .. '\\uff19' | '\\uff21' .. '\\uff3a' | '\\uff41' .. '\\uff5a' | '\\uff66' .. '\\uffbe' | '\\uffc2' .. '\\uffc7' | '\\uffca' .. '\\uffcf' | '\\uffd2' .. '\\uffd7' | '\\uffda' .. '\\uffdc' | '\\uffe0' .. '\\uffe1' | '\\uffe4' .. '\\uffe6' | '\\uffe8' | '\\uffed' .. '\\uffee' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='$'||(input.LA(1) >= '0' && input.LA(1) <= '9')||(input.LA(1) >= 'A' && input.LA(1) <= 'Z')||(input.LA(1) >= 'a' && input.LA(1) <= 'z')||(input.LA(1) >= '\u00A2' && input.LA(1) <= '\u00A7')||(input.LA(1) >= '\u00A9' && input.LA(1) <= '\u00AA')||input.LA(1)=='\u00AE'||input.LA(1)=='\u00B0'||(input.LA(1) >= '\u00B2' && input.LA(1) <= '\u00B3')||(input.LA(1) >= '\u00B5' && input.LA(1) <= '\u00B6')||(input.LA(1) >= '\u00B9' && input.LA(1) <= '\u00BA')||(input.LA(1) >= '\u00BC' && input.LA(1) <= '\u00BE')||(input.LA(1) >= '\u00C0' && input.LA(1) <= '\u00D6')||(input.LA(1) >= '\u00D8' && input.LA(1) <= '\u00F6')||(input.LA(1) >= '\u00F8' && input.LA(1) <= '\u0236')||(input.LA(1) >= '\u0250' && input.LA(1) <= '\u02C1')||(input.LA(1) >= '\u02C6' && input.LA(1) <= '\u02D1')||(input.LA(1) >= '\u02E0' && input.LA(1) <= '\u02E4')||input.LA(1)=='\u02EE'||(input.LA(1) >= '\u0300' && input.LA(1) <= '\u0357')||(input.LA(1) >= '\u035D' && input.LA(1) <= '\u036F')||input.LA(1)=='\u037A'||input.LA(1)=='\u0386'||(input.LA(1) >= '\u0388' && input.LA(1) <= '\u038A')||input.LA(1)=='\u038C'||(input.LA(1) >= '\u038E' && input.LA(1) <= '\u03A1')||(input.LA(1) >= '\u03A3' && input.LA(1) <= '\u03CE')||(input.LA(1) >= '\u03D0' && input.LA(1) <= '\u03F5')||(input.LA(1) >= '\u03F7' && input.LA(1) <= '\u03FB')||(input.LA(1) >= '\u0400' && input.LA(1) <= '\u0486')||(input.LA(1) >= '\u0488' && input.LA(1) <= '\u04CE')||(input.LA(1) >= '\u04D0' && input.LA(1) <= '\u04F5')||(input.LA(1) >= '\u04F8' && input.LA(1) <= '\u04F9')||(input.LA(1) >= '\u0500' && input.LA(1) <= '\u050F')||(input.LA(1) >= '\u0531' && input.LA(1) <= '\u0556')||input.LA(1)=='\u0559'||(input.LA(1) >= '\u0561' && input.LA(1) <= '\u0587')||(input.LA(1) >= '\u0591' && input.LA(1) <= '\u05A1')||(input.LA(1) >= '\u05A3' && input.LA(1) <= '\u05B9')||(input.LA(1) >= '\u05BB' && input.LA(1) <= '\u05BD')||input.LA(1)=='\u05BF'||(input.LA(1) >= '\u05C1' && input.LA(1) <= '\u05C2')||input.LA(1)=='\u05C4'||(input.LA(1) >= '\u05D0' && input.LA(1) <= '\u05EA')||(input.LA(1) >= '\u05F0' && input.LA(1) <= '\u05F2')||(input.LA(1) >= '\u060E' && input.LA(1) <= '\u0615')||(input.LA(1) >= '\u0621' && input.LA(1) <= '\u063A')||(input.LA(1) >= '\u0640' && input.LA(1) <= '\u0658')||(input.LA(1) >= '\u0660' && input.LA(1) <= '\u0669')||(input.LA(1) >= '\u066E' && input.LA(1) <= '\u06D3')||(input.LA(1) >= '\u06D5' && input.LA(1) <= '\u06DC')||(input.LA(1) >= '\u06DE' && input.LA(1) <= '\u06FF')||(input.LA(1) >= '\u0710' && input.LA(1) <= '\u074A')||(input.LA(1) >= '\u074D' && input.LA(1) <= '\u074F')||(input.LA(1) >= '\u0780' && input.LA(1) <= '\u07B1')||(input.LA(1) >= '\u0901' && input.LA(1) <= '\u0939')||(input.LA(1) >= '\u093C' && input.LA(1) <= '\u094D')||(input.LA(1) >= '\u0950' && input.LA(1) <= '\u0954')||(input.LA(1) >= '\u0958' && input.LA(1) <= '\u0963')||(input.LA(1) >= '\u0966' && input.LA(1) <= '\u096F')||(input.LA(1) >= '\u0981' && input.LA(1) <= '\u0983')||(input.LA(1) >= '\u0985' && input.LA(1) <= '\u098C')||(input.LA(1) >= '\u098F' && input.LA(1) <= '\u0990')||(input.LA(1) >= '\u0993' && input.LA(1) <= '\u09A8')||(input.LA(1) >= '\u09AA' && input.LA(1) <= '\u09B0')||input.LA(1)=='\u09B2'||(input.LA(1) >= '\u09B6' && input.LA(1) <= '\u09B9')||(input.LA(1) >= '\u09BC' && input.LA(1) <= '\u09C4')||(input.LA(1) >= '\u09C7' && input.LA(1) <= '\u09C8')||(input.LA(1) >= '\u09CB' && input.LA(1) <= '\u09CD')||input.LA(1)=='\u09D7'||(input.LA(1) >= '\u09DC' && input.LA(1) <= '\u09DD')||(input.LA(1) >= '\u09DF' && input.LA(1) <= '\u09E3')||(input.LA(1) >= '\u09E6' && input.LA(1) <= '\u09FA')||(input.LA(1) >= '\u0A01' && input.LA(1) <= '\u0A03')||(input.LA(1) >= '\u0A05' && input.LA(1) <= '\u0A0A')||(input.LA(1) >= '\u0A0F' && input.LA(1) <= '\u0A10')||(input.LA(1) >= '\u0A13' && input.LA(1) <= '\u0A28')||(input.LA(1) >= '\u0A2A' && input.LA(1) <= '\u0A30')||(input.LA(1) >= '\u0A32' && input.LA(1) <= '\u0A33')||(input.LA(1) >= '\u0A35' && input.LA(1) <= '\u0A36')||(input.LA(1) >= '\u0A38' && input.LA(1) <= '\u0A39')||input.LA(1)=='\u0A3C'||(input.LA(1) >= '\u0A3E' && input.LA(1) <= '\u0A42')||(input.LA(1) >= '\u0A47' && input.LA(1) <= '\u0A48')||(input.LA(1) >= '\u0A4B' && input.LA(1) <= '\u0A4D')||(input.LA(1) >= '\u0A59' && input.LA(1) <= '\u0A5C')||input.LA(1)=='\u0A5E'||(input.LA(1) >= '\u0A66' && input.LA(1) <= '\u0A74')||(input.LA(1) >= '\u0A81' && input.LA(1) <= '\u0A83')||(input.LA(1) >= '\u0A85' && input.LA(1) <= '\u0A8D')||(input.LA(1) >= '\u0A8F' && input.LA(1) <= '\u0A91')||(input.LA(1) >= '\u0A93' && input.LA(1) <= '\u0AA8')||(input.LA(1) >= '\u0AAA' && input.LA(1) <= '\u0AB0')||(input.LA(1) >= '\u0AB2' && input.LA(1) <= '\u0AB3')||(input.LA(1) >= '\u0AB5' && input.LA(1) <= '\u0AB9')||(input.LA(1) >= '\u0ABC' && input.LA(1) <= '\u0AC5')||(input.LA(1) >= '\u0AC7' && input.LA(1) <= '\u0AC9')||(input.LA(1) >= '\u0ACB' && input.LA(1) <= '\u0ACD')||input.LA(1)=='\u0AD0'||(input.LA(1) >= '\u0AE0' && input.LA(1) <= '\u0AE3')||(input.LA(1) >= '\u0AE6' && input.LA(1) <= '\u0AEF')||input.LA(1)=='\u0AF1'||(input.LA(1) >= '\u0B01' && input.LA(1) <= '\u0B03')||(input.LA(1) >= '\u0B05' && input.LA(1) <= '\u0B0C')||(input.LA(1) >= '\u0B0F' && input.LA(1) <= '\u0B10')||(input.LA(1) >= '\u0B13' && input.LA(1) <= '\u0B28')||(input.LA(1) >= '\u0B2A' && input.LA(1) <= '\u0B30')||(input.LA(1) >= '\u0B32' && input.LA(1) <= '\u0B33')||(input.LA(1) >= '\u0B35' && input.LA(1) <= '\u0B39')||(input.LA(1) >= '\u0B3C' && input.LA(1) <= '\u0B43')||(input.LA(1) >= '\u0B47' && input.LA(1) <= '\u0B48')||(input.LA(1) >= '\u0B4B' && input.LA(1) <= '\u0B4D')||(input.LA(1) >= '\u0B56' && input.LA(1) <= '\u0B57')||(input.LA(1) >= '\u0B5C' && input.LA(1) <= '\u0B5D')||(input.LA(1) >= '\u0B5F' && input.LA(1) <= '\u0B61')||(input.LA(1) >= '\u0B66' && input.LA(1) <= '\u0B71')||(input.LA(1) >= '\u0B82' && input.LA(1) <= '\u0B83')||(input.LA(1) >= '\u0B85' && input.LA(1) <= '\u0B8A')||(input.LA(1) >= '\u0B8E' && input.LA(1) <= '\u0B90')||(input.LA(1) >= '\u0B92' && input.LA(1) <= '\u0B95')||(input.LA(1) >= '\u0B99' && input.LA(1) <= '\u0B9A')||input.LA(1)=='\u0B9C'||(input.LA(1) >= '\u0B9E' && input.LA(1) <= '\u0B9F')||(input.LA(1) >= '\u0BA3' && input.LA(1) <= '\u0BA4')||(input.LA(1) >= '\u0BA8' && input.LA(1) <= '\u0BAA')||(input.LA(1) >= '\u0BAE' && input.LA(1) <= '\u0BB5')||(input.LA(1) >= '\u0BB7' && input.LA(1) <= '\u0BB9')||(input.LA(1) >= '\u0BBE' && input.LA(1) <= '\u0BC2')||(input.LA(1) >= '\u0BC6' && input.LA(1) <= '\u0BC8')||(input.LA(1) >= '\u0BCA' && input.LA(1) <= '\u0BCD')||input.LA(1)=='\u0BD7'||(input.LA(1) >= '\u0BE7' && input.LA(1) <= '\u0BFA')||(input.LA(1) >= '\u0C01' && input.LA(1) <= '\u0C03')||(input.LA(1) >= '\u0C05' && input.LA(1) <= '\u0C0C')||(input.LA(1) >= '\u0C0E' && input.LA(1) <= '\u0C10')||(input.LA(1) >= '\u0C12' && input.LA(1) <= '\u0C28')||(input.LA(1) >= '\u0C2A' && input.LA(1) <= '\u0C33')||(input.LA(1) >= '\u0C35' && input.LA(1) <= '\u0C39')||(input.LA(1) >= '\u0C3E' && input.LA(1) <= '\u0C44')||(input.LA(1) >= '\u0C46' && input.LA(1) <= '\u0C48')||(input.LA(1) >= '\u0C4A' && input.LA(1) <= '\u0C4D')||(input.LA(1) >= '\u0C55' && input.LA(1) <= '\u0C56')||(input.LA(1) >= '\u0C60' && input.LA(1) <= '\u0C61')||(input.LA(1) >= '\u0C66' && input.LA(1) <= '\u0C6F')||(input.LA(1) >= '\u0C82' && input.LA(1) <= '\u0C83')||(input.LA(1) >= '\u0C85' && input.LA(1) <= '\u0C8C')||(input.LA(1) >= '\u0C8E' && input.LA(1) <= '\u0C90')||(input.LA(1) >= '\u0C92' && input.LA(1) <= '\u0CA8')||(input.LA(1) >= '\u0CAA' && input.LA(1) <= '\u0CB3')||(input.LA(1) >= '\u0CB5' && input.LA(1) <= '\u0CB9')||(input.LA(1) >= '\u0CBC' && input.LA(1) <= '\u0CC4')||(input.LA(1) >= '\u0CC6' && input.LA(1) <= '\u0CC8')||(input.LA(1) >= '\u0CCA' && input.LA(1) <= '\u0CCD')||(input.LA(1) >= '\u0CD5' && input.LA(1) <= '\u0CD6')||input.LA(1)=='\u0CDE'||(input.LA(1) >= '\u0CE0' && input.LA(1) <= '\u0CE1')||(input.LA(1) >= '\u0CE6' && input.LA(1) <= '\u0CEF')||(input.LA(1) >= '\u0D02' && input.LA(1) <= '\u0D03')||(input.LA(1) >= '\u0D05' && input.LA(1) <= '\u0D0C')||(input.LA(1) >= '\u0D0E' && input.LA(1) <= '\u0D10')||(input.LA(1) >= '\u0D12' && input.LA(1) <= '\u0D28')||(input.LA(1) >= '\u0D2A' && input.LA(1) <= '\u0D39')||(input.LA(1) >= '\u0D3E' && input.LA(1) <= '\u0D43')||(input.LA(1) >= '\u0D46' && input.LA(1) <= '\u0D48')||(input.LA(1) >= '\u0D4A' && input.LA(1) <= '\u0D4D')||input.LA(1)=='\u0D57'||(input.LA(1) >= '\u0D60' && input.LA(1) <= '\u0D61')||(input.LA(1) >= '\u0D66' && input.LA(1) <= '\u0D6F')||(input.LA(1) >= '\u0D82' && input.LA(1) <= '\u0D83')||(input.LA(1) >= '\u0D85' && input.LA(1) <= '\u0D96')||(input.LA(1) >= '\u0D9A' && input.LA(1) <= '\u0DB1')||(input.LA(1) >= '\u0DB3' && input.LA(1) <= '\u0DBB')||input.LA(1)=='\u0DBD'||(input.LA(1) >= '\u0DC0' && input.LA(1) <= '\u0DC6')||input.LA(1)=='\u0DCA'||(input.LA(1) >= '\u0DCF' && input.LA(1) <= '\u0DD4')||input.LA(1)=='\u0DD6'||(input.LA(1) >= '\u0DD8' && input.LA(1) <= '\u0DDF')||(input.LA(1) >= '\u0DF2' && input.LA(1) <= '\u0DF3')||(input.LA(1) >= '\u0E01' && input.LA(1) <= '\u0E3A')||(input.LA(1) >= '\u0E3F' && input.LA(1) <= '\u0E4E')||(input.LA(1) >= '\u0E50' && input.LA(1) <= '\u0E59')||(input.LA(1) >= '\u0E81' && input.LA(1) <= '\u0E82')||input.LA(1)=='\u0E84'||(input.LA(1) >= '\u0E87' && input.LA(1) <= '\u0E88')||input.LA(1)=='\u0E8A'||input.LA(1)=='\u0E8D'||(input.LA(1) >= '\u0E94' && input.LA(1) <= '\u0E97')||(input.LA(1) >= '\u0E99' && input.LA(1) <= '\u0E9F')||(input.LA(1) >= '\u0EA1' && input.LA(1) <= '\u0EA3')||input.LA(1)=='\u0EA5'||input.LA(1)=='\u0EA7'||(input.LA(1) >= '\u0EAA' && input.LA(1) <= '\u0EAB')||(input.LA(1) >= '\u0EAD' && input.LA(1) <= '\u0EB9')||(input.LA(1) >= '\u0EBB' && input.LA(1) <= '\u0EBD')||(input.LA(1) >= '\u0EC0' && input.LA(1) <= '\u0EC4')||input.LA(1)=='\u0EC6'||(input.LA(1) >= '\u0EC8' && input.LA(1) <= '\u0ECD')||(input.LA(1) >= '\u0ED0' && input.LA(1) <= '\u0ED9')||(input.LA(1) >= '\u0EDC' && input.LA(1) <= '\u0EDD')||(input.LA(1) >= '\u0F00' && input.LA(1) <= '\u0F03')||(input.LA(1) >= '\u0F13' && input.LA(1) <= '\u0F39')||(input.LA(1) >= '\u0F3E' && input.LA(1) <= '\u0F47')||(input.LA(1) >= '\u0F49' && input.LA(1) <= '\u0F6A')||(input.LA(1) >= '\u0F71' && input.LA(1) <= '\u0F84')||(input.LA(1) >= '\u0F86' && input.LA(1) <= '\u0F8B')||(input.LA(1) >= '\u0F90' && input.LA(1) <= '\u0F97')||(input.LA(1) >= '\u0F99' && input.LA(1) <= '\u0FBC')||(input.LA(1) >= '\u0FBE' && input.LA(1) <= '\u0FCC')||input.LA(1)=='\u0FCF'||(input.LA(1) >= '\u1000' && input.LA(1) <= '\u1021')||(input.LA(1) >= '\u1023' && input.LA(1) <= '\u1027')||(input.LA(1) >= '\u1029' && input.LA(1) <= '\u102A')||(input.LA(1) >= '\u102C' && input.LA(1) <= '\u1032')||(input.LA(1) >= '\u1036' && input.LA(1) <= '\u1039')||(input.LA(1) >= '\u1040' && input.LA(1) <= '\u1049')||(input.LA(1) >= '\u1050' && input.LA(1) <= '\u1059')||(input.LA(1) >= '\u10A0' && input.LA(1) <= '\u10C5')||(input.LA(1) >= '\u10D0' && input.LA(1) <= '\u10F8')||(input.LA(1) >= '\u1100' && input.LA(1) <= '\u1159')||(input.LA(1) >= '\u115F' && input.LA(1) <= '\u11A2')||(input.LA(1) >= '\u11A8' && input.LA(1) <= '\u11F9')||(input.LA(1) >= '\u1200' && input.LA(1) <= '\u1206')||(input.LA(1) >= '\u1208' && input.LA(1) <= '\u1246')||input.LA(1)=='\u1248'||(input.LA(1) >= '\u124A' && input.LA(1) <= '\u124D')||(input.LA(1) >= '\u1250' && input.LA(1) <= '\u1256')||input.LA(1)=='\u1258'||(input.LA(1) >= '\u125A' && input.LA(1) <= '\u125D')||(input.LA(1) >= '\u1260' && input.LA(1) <= '\u1286')||input.LA(1)=='\u1288'||(input.LA(1) >= '\u128A' && input.LA(1) <= '\u128D')||(input.LA(1) >= '\u1290' && input.LA(1) <= '\u12AE')||input.LA(1)=='\u12B0'||(input.LA(1) >= '\u12B2' && input.LA(1) <= '\u12B5')||(input.LA(1) >= '\u12B8' && input.LA(1) <= '\u12BE')||input.LA(1)=='\u12C0'||(input.LA(1) >= '\u12C2' && input.LA(1) <= '\u12C5')||(input.LA(1) >= '\u12C8' && input.LA(1) <= '\u12CE')||(input.LA(1) >= '\u12D0' && input.LA(1) <= '\u12D6')||(input.LA(1) >= '\u12D8' && input.LA(1) <= '\u12EE')||(input.LA(1) >= '\u12F0' && input.LA(1) <= '\u130E')||input.LA(1)=='\u1310'||(input.LA(1) >= '\u1312' && input.LA(1) <= '\u1315')||(input.LA(1) >= '\u1318' && input.LA(1) <= '\u131E')||(input.LA(1) >= '\u1320' && input.LA(1) <= '\u1346')||(input.LA(1) >= '\u1348' && input.LA(1) <= '\u135A')||(input.LA(1) >= '\u1369' && input.LA(1) <= '\u137C')||(input.LA(1) >= '\u13A0' && input.LA(1) <= '\u13F4')||(input.LA(1) >= '\u1401' && input.LA(1) <= '\u166C')||(input.LA(1) >= '\u166F' && input.LA(1) <= '\u1676')||(input.LA(1) >= '\u1681' && input.LA(1) <= '\u169A')||(input.LA(1) >= '\u16A0' && input.LA(1) <= '\u16EA')||(input.LA(1) >= '\u16EE' && input.LA(1) <= '\u16F0')||(input.LA(1) >= '\u1700' && input.LA(1) <= '\u170C')||(input.LA(1) >= '\u170E' && input.LA(1) <= '\u1714')||(input.LA(1) >= '\u1720' && input.LA(1) <= '\u1734')||(input.LA(1) >= '\u1740' && input.LA(1) <= '\u1753')||(input.LA(1) >= '\u1760' && input.LA(1) <= '\u176C')||(input.LA(1) >= '\u176E' && input.LA(1) <= '\u1770')||(input.LA(1) >= '\u1772' && input.LA(1) <= '\u1773')||(input.LA(1) >= '\u1780' && input.LA(1) <= '\u17B3')||(input.LA(1) >= '\u17B6' && input.LA(1) <= '\u17D3')||input.LA(1)=='\u17D7'||(input.LA(1) >= '\u17DB' && input.LA(1) <= '\u17DD')||(input.LA(1) >= '\u17E0' && input.LA(1) <= '\u17E9')||(input.LA(1) >= '\u17F0' && input.LA(1) <= '\u17F9')||(input.LA(1) >= '\u180B' && input.LA(1) <= '\u180D')||(input.LA(1) >= '\u1810' && input.LA(1) <= '\u1819')||(input.LA(1) >= '\u1820' && input.LA(1) <= '\u1877')||(input.LA(1) >= '\u1880' && input.LA(1) <= '\u18A9')||(input.LA(1) >= '\u1900' && input.LA(1) <= '\u191C')||(input.LA(1) >= '\u1920' && input.LA(1) <= '\u192B')||(input.LA(1) >= '\u1930' && input.LA(1) <= '\u193B')||input.LA(1)=='\u1940'||(input.LA(1) >= '\u1946' && input.LA(1) <= '\u196D')||(input.LA(1) >= '\u1970' && input.LA(1) <= '\u1974')||(input.LA(1) >= '\u19E0' && input.LA(1) <= '\u19FF')||(input.LA(1) >= '\u1D00' && input.LA(1) <= '\u1D6B')||(input.LA(1) >= '\u1E00' && input.LA(1) <= '\u1E9B')||(input.LA(1) >= '\u1EA0' && input.LA(1) <= '\u1EF9')||(input.LA(1) >= '\u1F00' && input.LA(1) <= '\u1F15')||(input.LA(1) >= '\u1F18' && input.LA(1) <= '\u1F1D')||(input.LA(1) >= '\u1F20' && input.LA(1) <= '\u1F45')||(input.LA(1) >= '\u1F48' && input.LA(1) <= '\u1F4D')||(input.LA(1) >= '\u1F50' && input.LA(1) <= '\u1F57')||input.LA(1)=='\u1F59'||input.LA(1)=='\u1F5B'||input.LA(1)=='\u1F5D'||(input.LA(1) >= '\u1F5F' && input.LA(1) <= '\u1F7D')||(input.LA(1) >= '\u1F80' && input.LA(1) <= '\u1FB4')||(input.LA(1) >= '\u1FB6' && input.LA(1) <= '\u1FBC')||input.LA(1)=='\u1FBE'||(input.LA(1) >= '\u1FC2' && input.LA(1) <= '\u1FC4')||(input.LA(1) >= '\u1FC6' && input.LA(1) <= '\u1FCC')||(input.LA(1) >= '\u1FD0' && input.LA(1) <= '\u1FD3')||(input.LA(1) >= '\u1FD6' && input.LA(1) <= '\u1FDB')||(input.LA(1) >= '\u1FE0' && input.LA(1) <= '\u1FEC')||(input.LA(1) >= '\u1FF2' && input.LA(1) <= '\u1FF4')||(input.LA(1) >= '\u1FF6' && input.LA(1) <= '\u1FFC')||(input.LA(1) >= '\u2070' && input.LA(1) <= '\u2071')||(input.LA(1) >= '\u2074' && input.LA(1) <= '\u2079')||(input.LA(1) >= '\u207F' && input.LA(1) <= '\u2089')||(input.LA(1) >= '\u20A0' && input.LA(1) <= '\u20B1')||(input.LA(1) >= '\u20D0' && input.LA(1) <= '\u20EA')||(input.LA(1) >= '\u2100' && input.LA(1) <= '\u213B')||(input.LA(1) >= '\u213D' && input.LA(1) <= '\u213F')||(input.LA(1) >= '\u2145' && input.LA(1) <= '\u214A')||(input.LA(1) >= '\u2153' && input.LA(1) <= '\u2183')||(input.LA(1) >= '\u2195' && input.LA(1) <= '\u2199')||(input.LA(1) >= '\u219C' && input.LA(1) <= '\u219F')||(input.LA(1) >= '\u21A1' && input.LA(1) <= '\u21A2')||(input.LA(1) >= '\u21A4' && input.LA(1) <= '\u21A5')||(input.LA(1) >= '\u21A7' && input.LA(1) <= '\u21AD')||(input.LA(1) >= '\u21AF' && input.LA(1) <= '\u21CD')||(input.LA(1) >= '\u21D0' && input.LA(1) <= '\u21D1')||input.LA(1)=='\u21D3'||(input.LA(1) >= '\u21D5' && input.LA(1) <= '\u21F3')||(input.LA(1) >= '\u2300' && input.LA(1) <= '\u2307')||(input.LA(1) >= '\u230C' && input.LA(1) <= '\u231F')||(input.LA(1) >= '\u2322' && input.LA(1) <= '\u2328')||(input.LA(1) >= '\u232B' && input.LA(1) <= '\u237B')||(input.LA(1) >= '\u237D' && input.LA(1) <= '\u239A')||(input.LA(1) >= '\u23B7' && input.LA(1) <= '\u23D0')||(input.LA(1) >= '\u2400' && input.LA(1) <= '\u2426')||(input.LA(1) >= '\u2440' && input.LA(1) <= '\u244A')||(input.LA(1) >= '\u2460' && input.LA(1) <= '\u25B6')||(input.LA(1) >= '\u25B8' && input.LA(1) <= '\u25C0')||(input.LA(1) >= '\u25C2' && input.LA(1) <= '\u25F7')||(input.LA(1) >= '\u2600' && input.LA(1) <= '\u2617')||(input.LA(1) >= '\u2619' && input.LA(1) <= '\u266E')||(input.LA(1) >= '\u2670' && input.LA(1) <= '\u267D')||(input.LA(1) >= '\u2680' && input.LA(1) <= '\u2691')||(input.LA(1) >= '\u26A0' && input.LA(1) <= '\u26A1')||(input.LA(1) >= '\u2701' && input.LA(1) <= '\u2704')||(input.LA(1) >= '\u2706' && input.LA(1) <= '\u2709')||(input.LA(1) >= '\u270C' && input.LA(1) <= '\u2727')||(input.LA(1) >= '\u2729' && input.LA(1) <= '\u274B')||input.LA(1)=='\u274D'||(input.LA(1) >= '\u274F' && input.LA(1) <= '\u2752')||input.LA(1)=='\u2756'||(input.LA(1) >= '\u2758' && input.LA(1) <= '\u275E')||(input.LA(1) >= '\u2761' && input.LA(1) <= '\u2767')||(input.LA(1) >= '\u2776' && input.LA(1) <= '\u2794')||(input.LA(1) >= '\u2798' && input.LA(1) <= '\u27AF')||(input.LA(1) >= '\u27B1' && input.LA(1) <= '\u27BE')||(input.LA(1) >= '\u2800' && input.LA(1) <= '\u28FF')||(input.LA(1) >= '\u2B00' && input.LA(1) <= '\u2B0D')||(input.LA(1) >= '\u2E80' && input.LA(1) <= '\u2E99')||(input.LA(1) >= '\u2E9B' && input.LA(1) <= '\u2EF3')||(input.LA(1) >= '\u2F00' && input.LA(1) <= '\u2FD5')||(input.LA(1) >= '\u2FF0' && input.LA(1) <= '\u2FFB')||(input.LA(1) >= '\u3004' && input.LA(1) <= '\u3007')||(input.LA(1) >= '\u3012' && input.LA(1) <= '\u3013')||(input.LA(1) >= '\u3020' && input.LA(1) <= '\u302F')||(input.LA(1) >= '\u3031' && input.LA(1) <= '\u303C')||(input.LA(1) >= '\u303E' && input.LA(1) <= '\u303F')||(input.LA(1) >= '\u3041' && input.LA(1) <= '\u3096')||(input.LA(1) >= '\u3099' && input.LA(1) <= '\u309A')||(input.LA(1) >= '\u309D' && input.LA(1) <= '\u309F')||(input.LA(1) >= '\u30A1' && input.LA(1) <= '\u30FA')||(input.LA(1) >= '\u30FC' && input.LA(1) <= '\u30FF')||(input.LA(1) >= '\u3105' && input.LA(1) <= '\u312C')||(input.LA(1) >= '\u3131' && input.LA(1) <= '\u318E')||(input.LA(1) >= '\u3190' && input.LA(1) <= '\u31B7')||(input.LA(1) >= '\u31F0' && input.LA(1) <= '\u321E')||(input.LA(1) >= '\u3220' && input.LA(1) <= '\u3243')||(input.LA(1) >= '\u3250' && input.LA(1) <= '\u327D')||(input.LA(1) >= '\u327F' && input.LA(1) <= '\u32FE')||(input.LA(1) >= '\u3300' && input.LA(1) <= '\u4DB5')||(input.LA(1) >= '\u4DC0' && input.LA(1) <= '\u9FA5')||(input.LA(1) >= '\uA000' && input.LA(1) <= '\uA48C')||(input.LA(1) >= '\uA490' && input.LA(1) <= '\uA4C6')||(input.LA(1) >= '\uAC00' && input.LA(1) <= '\uD7A3')||(input.LA(1) >= '\uF900' && input.LA(1) <= '\uFA2D')||(input.LA(1) >= '\uFA30' && input.LA(1) <= '\uFA6A')||(input.LA(1) >= '\uFB00' && input.LA(1) <= '\uFB06')||(input.LA(1) >= '\uFB13' && input.LA(1) <= '\uFB17')||(input.LA(1) >= '\uFB1D' && input.LA(1) <= '\uFB28')||(input.LA(1) >= '\uFB2A' && input.LA(1) <= '\uFB36')||(input.LA(1) >= '\uFB38' && input.LA(1) <= '\uFB3C')||input.LA(1)=='\uFB3E'||(input.LA(1) >= '\uFB40' && input.LA(1) <= '\uFB41')||(input.LA(1) >= '\uFB43' && input.LA(1) <= '\uFB44')||(input.LA(1) >= '\uFB46' && input.LA(1) <= '\uFBB1')||(input.LA(1) >= '\uFBD3' && input.LA(1) <= '\uFD3D')||(input.LA(1) >= '\uFD50' && input.LA(1) <= '\uFD8F')||(input.LA(1) >= '\uFD92' && input.LA(1) <= '\uFDC7')||(input.LA(1) >= '\uFDF0' && input.LA(1) <= '\uFDFD')||(input.LA(1) >= '\uFE00' && input.LA(1) <= '\uFE0F')||(input.LA(1) >= '\uFE20' && input.LA(1) <= '\uFE23')||input.LA(1)=='\uFE69'||(input.LA(1) >= '\uFE70' && input.LA(1) <= '\uFE74')||(input.LA(1) >= '\uFE76' && input.LA(1) <= '\uFEFC')||input.LA(1)=='\uFF04'||(input.LA(1) >= '\uFF10' && input.LA(1) <= '\uFF19')||(input.LA(1) >= '\uFF21' && input.LA(1) <= '\uFF3A')||(input.LA(1) >= '\uFF41' && input.LA(1) <= '\uFF5A')||(input.LA(1) >= '\uFF66' && input.LA(1) <= '\uFFBE')||(input.LA(1) >= '\uFFC2' && input.LA(1) <= '\uFFC7')||(input.LA(1) >= '\uFFCA' && input.LA(1) <= '\uFFCF')||(input.LA(1) >= '\uFFD2' && input.LA(1) <= '\uFFD7')||(input.LA(1) >= '\uFFDA' && input.LA(1) <= '\uFFDC')||(input.LA(1) >= '\uFFE0' && input.LA(1) <= '\uFFE1')||(input.LA(1) >= '\uFFE4' && input.LA(1) <= '\uFFE6')||input.LA(1)=='\uFFE8'||(input.LA(1) >= '\uFFED' && input.LA(1) <= '\uFFEE') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "START_WORD" + + // $ANTLR start "IN_WORD" + public final void mIN_WORD() throws RecognitionException { + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1995:9: ( '\\u0021' .. '\\u0027' | '\\u002b' | '\\u002d' | '\\u002f' .. '\\u0039' | '\\u003b' | '\\u003d' | '\\u0040' .. '\\u005a' | '\\u005f' | '\\u0061' .. '\\u007a' | '\\u007c' | '\\u00a1' .. '\\u00a7' | '\\u00a9' .. '\\u00aa' | '\\u00ac' | '\\u00ae' | '\\u00b0' .. '\\u00b3' | '\\u00b5' .. '\\u00b7' | '\\u00b9' .. '\\u00ba' | '\\u00bc' .. '\\u0236' | '\\u0250' .. '\\u02c1' | '\\u02c6' .. '\\u02d1' | '\\u02e0' .. '\\u02e4' | '\\u02ee' | '\\u0300' .. '\\u0357' | '\\u035d' .. '\\u036f' | '\\u037a' .. '\\u037a' | '\\u037e' .. '\\u037e' | '\\u0386' .. '\\u038a' | '\\u038c' .. '\\u038c' | '\\u038e' .. '\\u03a1' | '\\u03a3' .. '\\u03ce' | '\\u03d0' .. '\\u03fb' | '\\u0400' .. '\\u0486' | '\\u0488' .. '\\u04ce' | '\\u04d0' .. '\\u04f5' | '\\u04f8' .. '\\u04f9' | '\\u0500' .. '\\u050f' | '\\u0531' .. '\\u0556' | '\\u0559' .. '\\u055f' | '\\u0561' .. '\\u0587' | '\\u0589' .. '\\u058a' | '\\u0591' .. '\\u05a1' | '\\u05a3' .. '\\u05b9' | '\\u05bb' .. '\\u05c4' | '\\u05d0' .. '\\u05ea' | '\\u05f0' .. '\\u05f4' | '\\u060c' .. '\\u0615' | '\\u061b' .. '\\u061b' | '\\u061f' .. '\\u061f' | '\\u0621' .. '\\u063a' | '\\u0640' .. '\\u0658' | '\\u0660' .. '\\u06dc' | '\\u06de' .. '\\u070d' | '\\u0710' .. '\\u074a' | '\\u074d' .. '\\u074f' | '\\u0780' .. '\\u07b1' | '\\u0901' .. '\\u0939' | '\\u093c' .. '\\u094d' | '\\u0950' .. '\\u0954' | '\\u0958' .. '\\u0970' | '\\u0981' .. '\\u0983' | '\\u0985' .. '\\u098c' | '\\u098f' .. '\\u0990' | '\\u0993' .. '\\u09a8' | '\\u09aa' .. '\\u09b0' | '\\u09b2' .. '\\u09b2' | '\\u09b6' .. '\\u09b9' | '\\u09bc' .. '\\u09c4' | '\\u09c7' .. '\\u09c8' | '\\u09cb' .. '\\u09cd' | '\\u09d7' .. '\\u09d7' | '\\u09dc' .. '\\u09dd' | '\\u09df' .. '\\u09e3' | '\\u09e6' .. '\\u09fa' | '\\u0a01' .. '\\u0a03' | '\\u0a05' .. '\\u0a0a' | '\\u0a0f' .. '\\u0a10' | '\\u0a13' .. '\\u0a28' | '\\u0a2a' .. '\\u0a30' | '\\u0a32' .. '\\u0a33' | '\\u0a35' .. '\\u0a36' | '\\u0a38' .. '\\u0a39' | '\\u0a3c' .. '\\u0a3c' | '\\u0a3e' .. '\\u0a42' | '\\u0a47' .. '\\u0a48' | '\\u0a4b' .. '\\u0a4d' | '\\u0a59' .. '\\u0a5c' | '\\u0a5e' .. '\\u0a5e' | '\\u0a66' .. '\\u0a74' | '\\u0a81' .. '\\u0a83' | '\\u0a85' .. '\\u0a8d' | '\\u0a8f' .. '\\u0a91' | '\\u0a93' .. '\\u0aa8' | '\\u0aaa' .. '\\u0ab0' | '\\u0ab2' .. '\\u0ab3' | '\\u0ab5' .. '\\u0ab9' | '\\u0abc' .. '\\u0ac5' | '\\u0ac7' .. '\\u0ac9' | '\\u0acb' .. '\\u0acd' | '\\u0ad0' .. '\\u0ad0' | '\\u0ae0' .. '\\u0ae3' | '\\u0ae6' .. '\\u0aef' | '\\u0af1' .. '\\u0af1' | '\\u0b01' .. '\\u0b03' | '\\u0b05' .. '\\u0b0c' | '\\u0b0f' .. '\\u0b10' | '\\u0b13' .. '\\u0b28' | '\\u0b2a' .. '\\u0b30' | '\\u0b32' .. '\\u0b33' | '\\u0b35' .. '\\u0b39' | '\\u0b3c' .. '\\u0b43' | '\\u0b47' .. '\\u0b48' | '\\u0b4b' .. '\\u0b4d' | '\\u0b56' .. '\\u0b57' | '\\u0b5c' .. '\\u0b5d' | '\\u0b5f' .. '\\u0b61' | '\\u0b66' .. '\\u0b71' | '\\u0b82' .. '\\u0b83' | '\\u0b85' .. '\\u0b8a' | '\\u0b8e' .. '\\u0b90' | '\\u0b92' .. '\\u0b95' | '\\u0b99' .. '\\u0b9a' | '\\u0b9c' .. '\\u0b9c' | '\\u0b9e' .. '\\u0b9f' | '\\u0ba3' .. '\\u0ba4' | '\\u0ba8' .. '\\u0baa' | '\\u0bae' .. '\\u0bb5' | '\\u0bb7' .. '\\u0bb9' | '\\u0bbe' .. '\\u0bc2' | '\\u0bc6' .. '\\u0bc8' | '\\u0bca' .. '\\u0bcd' | '\\u0bd7' .. '\\u0bd7' | '\\u0be7' .. '\\u0bfa' | '\\u0c01' .. '\\u0c03' | '\\u0c05' .. '\\u0c0c' | '\\u0c0e' .. '\\u0c10' | '\\u0c12' .. '\\u0c28' | '\\u0c2a' .. '\\u0c33' | '\\u0c35' .. '\\u0c39' | '\\u0c3e' .. '\\u0c44' | '\\u0c46' .. '\\u0c48' | '\\u0c4a' .. '\\u0c4d' | '\\u0c55' .. '\\u0c56' | '\\u0c60' .. '\\u0c61' | '\\u0c66' .. '\\u0c6f' | '\\u0c82' .. '\\u0c83' | '\\u0c85' .. '\\u0c8c' | '\\u0c8e' .. '\\u0c90' | '\\u0c92' .. '\\u0ca8' | '\\u0caa' .. '\\u0cb3' | '\\u0cb5' .. '\\u0cb9' | '\\u0cbc' .. '\\u0cc4' | '\\u0cc6' .. '\\u0cc8' | '\\u0cca' .. '\\u0ccd' | '\\u0cd5' .. '\\u0cd6' | '\\u0cde' .. '\\u0cde' | '\\u0ce0' .. '\\u0ce1' | '\\u0ce6' .. '\\u0cef' | '\\u0d02' .. '\\u0d03' | '\\u0d05' .. '\\u0d0c' | '\\u0d0e' .. '\\u0d10' | '\\u0d12' .. '\\u0d28' | '\\u0d2a' .. '\\u0d39' | '\\u0d3e' .. '\\u0d43' | '\\u0d46' .. '\\u0d48' | '\\u0d4a' .. '\\u0d4d' | '\\u0d57' .. '\\u0d57' | '\\u0d60' .. '\\u0d61' | '\\u0d66' .. '\\u0d6f' | '\\u0d82' .. '\\u0d83' | '\\u0d85' .. '\\u0d96' | '\\u0d9a' .. '\\u0db1' | '\\u0db3' .. '\\u0dbb' | '\\u0dbd' .. '\\u0dbd' | '\\u0dc0' .. '\\u0dc6' | '\\u0dca' .. '\\u0dca' | '\\u0dcf' .. '\\u0dd4' | '\\u0dd6' .. '\\u0dd6' | '\\u0dd8' .. '\\u0ddf' | '\\u0df2' .. '\\u0df4' | '\\u0e01' .. '\\u0e3a' | '\\u0e3f' .. '\\u0e5b' | '\\u0e81' .. '\\u0e82' | '\\u0e84' .. '\\u0e84' | '\\u0e87' .. '\\u0e88' | '\\u0e8a' .. '\\u0e8a' | '\\u0e8d' .. '\\u0e8d' | '\\u0e94' .. '\\u0e97' | '\\u0e99' .. '\\u0e9f' | '\\u0ea1' .. '\\u0ea3' | '\\u0ea5' .. '\\u0ea5' | '\\u0ea7' .. '\\u0ea7' | '\\u0eaa' .. '\\u0eab' | '\\u0ead' .. '\\u0eb9' | '\\u0ebb' .. '\\u0ebd' | '\\u0ec0' .. '\\u0ec4' | '\\u0ec6' .. '\\u0ec6' | '\\u0ec8' .. '\\u0ecd' | '\\u0ed0' .. '\\u0ed9' | '\\u0edc' .. '\\u0edd' | '\\u0f00' .. '\\u0f39' | '\\u0f3e' .. '\\u0f47' | '\\u0f49' .. '\\u0f6a' | '\\u0f71' .. '\\u0f8b' | '\\u0f90' .. '\\u0f97' | '\\u0f99' .. '\\u0fbc' | '\\u0fbe' .. '\\u0fcc' | '\\u0fcf' .. '\\u0fcf' | '\\u1000' .. '\\u1021' | '\\u1023' .. '\\u1027' | '\\u1029' .. '\\u102a' | '\\u102c' .. '\\u1032' | '\\u1036' .. '\\u1039' | '\\u1040' .. '\\u1059' | '\\u10a0' .. '\\u10c5' | '\\u10d0' .. '\\u10f8' | '\\u10fb' .. '\\u10fb' | '\\u1100' .. '\\u1159' | '\\u115f' .. '\\u11a2' | '\\u11a8' .. '\\u11f9' | '\\u1200' .. '\\u1206' | '\\u1208' .. '\\u1246' | '\\u1248' .. '\\u1248' | '\\u124a' .. '\\u124d' | '\\u1250' .. '\\u1256' | '\\u1258' .. '\\u1258' | '\\u125a' .. '\\u125d' | '\\u1260' .. '\\u1286' | '\\u1288' .. '\\u1288' | '\\u128a' .. '\\u128d' | '\\u1290' .. '\\u12ae' | '\\u12b0' .. '\\u12b0' | '\\u12b2' .. '\\u12b5' | '\\u12b8' .. '\\u12be' | '\\u12c0' .. '\\u12c0' | '\\u12c2' .. '\\u12c5' | '\\u12c8' .. '\\u12ce' | '\\u12d0' .. '\\u12d6' | '\\u12d8' .. '\\u12ee' | '\\u12f0' .. '\\u130e' | '\\u1310' .. '\\u1310' | '\\u1312' .. '\\u1315' | '\\u1318' .. '\\u131e' | '\\u1320' .. '\\u1346' | '\\u1348' .. '\\u135a' | '\\u1361' .. '\\u137c' | '\\u13a0' .. '\\u13f4' | '\\u1401' .. '\\u1676' | '\\u1681' .. '\\u169a' | '\\u16a0' .. '\\u16f0' | '\\u1700' .. '\\u170c' | '\\u170e' .. '\\u1714' | '\\u1720' .. '\\u1736' | '\\u1740' .. '\\u1753' | '\\u1760' .. '\\u176c' | '\\u176e' .. '\\u1770' | '\\u1772' .. '\\u1773' | '\\u1780' .. '\\u17b3' | '\\u17b6' .. '\\u17dd' | '\\u17e0' .. '\\u17e9' | '\\u17f0' .. '\\u17f9' | '\\u1800' .. '\\u180d' | '\\u1810' .. '\\u1819' | '\\u1820' .. '\\u1877' | '\\u1880' .. '\\u18a9' | '\\u1900' .. '\\u191c' | '\\u1920' .. '\\u192b' | '\\u1930' .. '\\u193b' | '\\u1940' .. '\\u1940' | '\\u1944' .. '\\u196d' | '\\u1970' .. '\\u1974' | '\\u19e0' .. '\\u19ff' | '\\u1d00' .. '\\u1d6b' | '\\u1e00' .. '\\u1e9b' | '\\u1ea0' .. '\\u1ef9' | '\\u1f00' .. '\\u1f15' | '\\u1f18' .. '\\u1f1d' | '\\u1f20' .. '\\u1f45' | '\\u1f48' .. '\\u1f4d' | '\\u1f50' .. '\\u1f57' | '\\u1f59' .. '\\u1f59' | '\\u1f5b' .. '\\u1f5b' | '\\u1f5d' .. '\\u1f5d' | '\\u1f5f' .. '\\u1f7d' | '\\u1f80' .. '\\u1fb4' | '\\u1fb6' .. '\\u1fbc' | '\\u1fbe' | '\\u1fc2' .. '\\u1fc4' | '\\u1fc6' .. '\\u1fcc' | '\\u1fd0' .. '\\u1fd3' | '\\u1fd6' .. '\\u1fdb' | '\\u1fe0' .. '\\u1fec' | '\\u1ff2' .. '\\u1ff4' | '\\u1ff6' .. '\\u1ffc' | '\\u2010' .. '\\u2017' | '\\u2020' .. '\\u2027' | '\\u2030' .. '\\u2038' | '\\u203b' .. '\\u2044' | '\\u2047' .. '\\u2054' | '\\u2057' .. '\\u2057' | '\\u2070' .. '\\u2071' | '\\u2074' .. '\\u207c' | '\\u207f' .. '\\u208c' | '\\u20a0' .. '\\u20b1' | '\\u20d0' .. '\\u20ea' | '\\u2100' .. '\\u213b' | '\\u213d' .. '\\u214b' | '\\u2153' .. '\\u2183' | '\\u2190' .. '\\u2328' | '\\u232b' .. '\\u23b3' | '\\u23b6' .. '\\u23d0' | '\\u2400' .. '\\u2426' | '\\u2440' .. '\\u244a' | '\\u2460' .. '\\u2617' | '\\u2619' .. '\\u267d' | '\\u2680' .. '\\u2691' | '\\u26a0' .. '\\u26a1' | '\\u2701' .. '\\u2704' | '\\u2706' .. '\\u2709' | '\\u270c' .. '\\u2727' | '\\u2729' .. '\\u274b' | '\\u274d' .. '\\u274d' | '\\u274f' .. '\\u2752' | '\\u2756' .. '\\u2756' | '\\u2758' .. '\\u275e' | '\\u2761' .. '\\u2767' | '\\u2776' .. '\\u2794' | '\\u2798' .. '\\u27af' | '\\u27b1' .. '\\u27be' | '\\u27d0' .. '\\u27e5' | '\\u27f0' .. '\\u2982' | '\\u2999' .. '\\u29d7' | '\\u29dc' .. '\\u29fb' | '\\u29fe' .. '\\u2b0d' | '\\u2e80' .. '\\u2e99' | '\\u2e9b' .. '\\u2ef3' | '\\u2f00' .. '\\u2fd5' | '\\u2ff0' .. '\\u2ffb' | '\\u3001' .. '\\u3007' | '\\u3012' .. '\\u3013' | '\\u301c' | '\\u3020' .. '\\u303f' | '\\u3041' .. '\\u3096' | '\\u3099' .. '\\u309a' | '\\u309d' .. '\\u30ff' | '\\u3105' .. '\\u312c' | '\\u3131' .. '\\u318e' | '\\u3190' .. '\\u31b7' | '\\u31f0' .. '\\u321e' | '\\u3220' .. '\\u3243' | '\\u3250' .. '\\u327d' | '\\u327f' .. '\\u32fe' | '\\u3300' .. '\\u4db5' | '\\u4dc0' .. '\\u9fa5' | '\\ua000' .. '\\ua48c' | '\\ua490' .. '\\ua4c6' | '\\uac00' .. '\\ud7a3' | '\\uf900' .. '\\ufa2d' | '\\ufa30' .. '\\ufa6a' | '\\ufb00' .. '\\ufb06' | '\\ufb13' .. '\\ufb17' | '\\ufb1d' .. '\\ufb36' | '\\ufb38' .. '\\ufb3c' | '\\ufb3e' .. '\\ufb3e' | '\\ufb40' .. '\\ufb41' | '\\ufb43' .. '\\ufb44' | '\\ufb46' .. '\\ufbb1' | '\\ufbd3' .. '\\ufd3d' | '\\ufd50' .. '\\ufd8f' | '\\ufd92' .. '\\ufdc7' | '\\ufdf0' .. '\\ufdfd' | '\\ufe00' .. '\\ufe0f' | '\\ufe20' .. '\\ufe23' | '\\ufe30' .. '\\ufe34' | '\\ufe45' .. '\\ufe46' | '\\ufe49' .. '\\ufe52' | '\\ufe54' .. '\\ufe58' | '\\ufe5f' .. '\\ufe66' | '\\ufe68' .. '\\ufe6b' | '\\ufe70' .. '\\ufe74' | '\\ufe76' .. '\\ufefc' | '\\uff01' .. '\\uff07' | '\\uff0a' .. '\\uff3a' | '\\uff3c' | '\\uff3f' | '\\uff41' .. '\\uff5a' | '\\uff5c' | '\\uff5e' | '\\uff61' | '\\uff64' .. '\\uffbe' | '\\uffc2' .. '\\uffc7' | '\\uffca' .. '\\uffcf' | '\\uffd2' .. '\\uffd7' | '\\uffda' .. '\\uffdc' | '\\uffe0' .. '\\uffe2' | '\\uffe4' .. '\\uffe6' | '\\uffe8' .. '\\uffee' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( (input.LA(1) >= '!' && input.LA(1) <= '\'')||input.LA(1)=='+'||input.LA(1)=='-'||(input.LA(1) >= '/' && input.LA(1) <= '9')||input.LA(1)==';'||input.LA(1)=='='||(input.LA(1) >= '@' && input.LA(1) <= 'Z')||input.LA(1)=='_'||(input.LA(1) >= 'a' && input.LA(1) <= 'z')||input.LA(1)=='|'||(input.LA(1) >= '\u00A1' && input.LA(1) <= '\u00A7')||(input.LA(1) >= '\u00A9' && input.LA(1) <= '\u00AA')||input.LA(1)=='\u00AC'||input.LA(1)=='\u00AE'||(input.LA(1) >= '\u00B0' && input.LA(1) <= '\u00B3')||(input.LA(1) >= '\u00B5' && input.LA(1) <= '\u00B7')||(input.LA(1) >= '\u00B9' && input.LA(1) <= '\u00BA')||(input.LA(1) >= '\u00BC' && input.LA(1) <= '\u0236')||(input.LA(1) >= '\u0250' && input.LA(1) <= '\u02C1')||(input.LA(1) >= '\u02C6' && input.LA(1) <= '\u02D1')||(input.LA(1) >= '\u02E0' && input.LA(1) <= '\u02E4')||input.LA(1)=='\u02EE'||(input.LA(1) >= '\u0300' && input.LA(1) <= '\u0357')||(input.LA(1) >= '\u035D' && input.LA(1) <= '\u036F')||input.LA(1)=='\u037A'||input.LA(1)=='\u037E'||(input.LA(1) >= '\u0386' && input.LA(1) <= '\u038A')||input.LA(1)=='\u038C'||(input.LA(1) >= '\u038E' && input.LA(1) <= '\u03A1')||(input.LA(1) >= '\u03A3' && input.LA(1) <= '\u03CE')||(input.LA(1) >= '\u03D0' && input.LA(1) <= '\u03FB')||(input.LA(1) >= '\u0400' && input.LA(1) <= '\u0486')||(input.LA(1) >= '\u0488' && input.LA(1) <= '\u04CE')||(input.LA(1) >= '\u04D0' && input.LA(1) <= '\u04F5')||(input.LA(1) >= '\u04F8' && input.LA(1) <= '\u04F9')||(input.LA(1) >= '\u0500' && input.LA(1) <= '\u050F')||(input.LA(1) >= '\u0531' && input.LA(1) <= '\u0556')||(input.LA(1) >= '\u0559' && input.LA(1) <= '\u055F')||(input.LA(1) >= '\u0561' && input.LA(1) <= '\u0587')||(input.LA(1) >= '\u0589' && input.LA(1) <= '\u058A')||(input.LA(1) >= '\u0591' && input.LA(1) <= '\u05A1')||(input.LA(1) >= '\u05A3' && input.LA(1) <= '\u05B9')||(input.LA(1) >= '\u05BB' && input.LA(1) <= '\u05C4')||(input.LA(1) >= '\u05D0' && input.LA(1) <= '\u05EA')||(input.LA(1) >= '\u05F0' && input.LA(1) <= '\u05F4')||(input.LA(1) >= '\u060C' && input.LA(1) <= '\u0615')||input.LA(1)=='\u061B'||input.LA(1)=='\u061F'||(input.LA(1) >= '\u0621' && input.LA(1) <= '\u063A')||(input.LA(1) >= '\u0640' && input.LA(1) <= '\u0658')||(input.LA(1) >= '\u0660' && input.LA(1) <= '\u06DC')||(input.LA(1) >= '\u06DE' && input.LA(1) <= '\u070D')||(input.LA(1) >= '\u0710' && input.LA(1) <= '\u074A')||(input.LA(1) >= '\u074D' && input.LA(1) <= '\u074F')||(input.LA(1) >= '\u0780' && input.LA(1) <= '\u07B1')||(input.LA(1) >= '\u0901' && input.LA(1) <= '\u0939')||(input.LA(1) >= '\u093C' && input.LA(1) <= '\u094D')||(input.LA(1) >= '\u0950' && input.LA(1) <= '\u0954')||(input.LA(1) >= '\u0958' && input.LA(1) <= '\u0970')||(input.LA(1) >= '\u0981' && input.LA(1) <= '\u0983')||(input.LA(1) >= '\u0985' && input.LA(1) <= '\u098C')||(input.LA(1) >= '\u098F' && input.LA(1) <= '\u0990')||(input.LA(1) >= '\u0993' && input.LA(1) <= '\u09A8')||(input.LA(1) >= '\u09AA' && input.LA(1) <= '\u09B0')||input.LA(1)=='\u09B2'||(input.LA(1) >= '\u09B6' && input.LA(1) <= '\u09B9')||(input.LA(1) >= '\u09BC' && input.LA(1) <= '\u09C4')||(input.LA(1) >= '\u09C7' && input.LA(1) <= '\u09C8')||(input.LA(1) >= '\u09CB' && input.LA(1) <= '\u09CD')||input.LA(1)=='\u09D7'||(input.LA(1) >= '\u09DC' && input.LA(1) <= '\u09DD')||(input.LA(1) >= '\u09DF' && input.LA(1) <= '\u09E3')||(input.LA(1) >= '\u09E6' && input.LA(1) <= '\u09FA')||(input.LA(1) >= '\u0A01' && input.LA(1) <= '\u0A03')||(input.LA(1) >= '\u0A05' && input.LA(1) <= '\u0A0A')||(input.LA(1) >= '\u0A0F' && input.LA(1) <= '\u0A10')||(input.LA(1) >= '\u0A13' && input.LA(1) <= '\u0A28')||(input.LA(1) >= '\u0A2A' && input.LA(1) <= '\u0A30')||(input.LA(1) >= '\u0A32' && input.LA(1) <= '\u0A33')||(input.LA(1) >= '\u0A35' && input.LA(1) <= '\u0A36')||(input.LA(1) >= '\u0A38' && input.LA(1) <= '\u0A39')||input.LA(1)=='\u0A3C'||(input.LA(1) >= '\u0A3E' && input.LA(1) <= '\u0A42')||(input.LA(1) >= '\u0A47' && input.LA(1) <= '\u0A48')||(input.LA(1) >= '\u0A4B' && input.LA(1) <= '\u0A4D')||(input.LA(1) >= '\u0A59' && input.LA(1) <= '\u0A5C')||input.LA(1)=='\u0A5E'||(input.LA(1) >= '\u0A66' && input.LA(1) <= '\u0A74')||(input.LA(1) >= '\u0A81' && input.LA(1) <= '\u0A83')||(input.LA(1) >= '\u0A85' && input.LA(1) <= '\u0A8D')||(input.LA(1) >= '\u0A8F' && input.LA(1) <= '\u0A91')||(input.LA(1) >= '\u0A93' && input.LA(1) <= '\u0AA8')||(input.LA(1) >= '\u0AAA' && input.LA(1) <= '\u0AB0')||(input.LA(1) >= '\u0AB2' && input.LA(1) <= '\u0AB3')||(input.LA(1) >= '\u0AB5' && input.LA(1) <= '\u0AB9')||(input.LA(1) >= '\u0ABC' && input.LA(1) <= '\u0AC5')||(input.LA(1) >= '\u0AC7' && input.LA(1) <= '\u0AC9')||(input.LA(1) >= '\u0ACB' && input.LA(1) <= '\u0ACD')||input.LA(1)=='\u0AD0'||(input.LA(1) >= '\u0AE0' && input.LA(1) <= '\u0AE3')||(input.LA(1) >= '\u0AE6' && input.LA(1) <= '\u0AEF')||input.LA(1)=='\u0AF1'||(input.LA(1) >= '\u0B01' && input.LA(1) <= '\u0B03')||(input.LA(1) >= '\u0B05' && input.LA(1) <= '\u0B0C')||(input.LA(1) >= '\u0B0F' && input.LA(1) <= '\u0B10')||(input.LA(1) >= '\u0B13' && input.LA(1) <= '\u0B28')||(input.LA(1) >= '\u0B2A' && input.LA(1) <= '\u0B30')||(input.LA(1) >= '\u0B32' && input.LA(1) <= '\u0B33')||(input.LA(1) >= '\u0B35' && input.LA(1) <= '\u0B39')||(input.LA(1) >= '\u0B3C' && input.LA(1) <= '\u0B43')||(input.LA(1) >= '\u0B47' && input.LA(1) <= '\u0B48')||(input.LA(1) >= '\u0B4B' && input.LA(1) <= '\u0B4D')||(input.LA(1) >= '\u0B56' && input.LA(1) <= '\u0B57')||(input.LA(1) >= '\u0B5C' && input.LA(1) <= '\u0B5D')||(input.LA(1) >= '\u0B5F' && input.LA(1) <= '\u0B61')||(input.LA(1) >= '\u0B66' && input.LA(1) <= '\u0B71')||(input.LA(1) >= '\u0B82' && input.LA(1) <= '\u0B83')||(input.LA(1) >= '\u0B85' && input.LA(1) <= '\u0B8A')||(input.LA(1) >= '\u0B8E' && input.LA(1) <= '\u0B90')||(input.LA(1) >= '\u0B92' && input.LA(1) <= '\u0B95')||(input.LA(1) >= '\u0B99' && input.LA(1) <= '\u0B9A')||input.LA(1)=='\u0B9C'||(input.LA(1) >= '\u0B9E' && input.LA(1) <= '\u0B9F')||(input.LA(1) >= '\u0BA3' && input.LA(1) <= '\u0BA4')||(input.LA(1) >= '\u0BA8' && input.LA(1) <= '\u0BAA')||(input.LA(1) >= '\u0BAE' && input.LA(1) <= '\u0BB5')||(input.LA(1) >= '\u0BB7' && input.LA(1) <= '\u0BB9')||(input.LA(1) >= '\u0BBE' && input.LA(1) <= '\u0BC2')||(input.LA(1) >= '\u0BC6' && input.LA(1) <= '\u0BC8')||(input.LA(1) >= '\u0BCA' && input.LA(1) <= '\u0BCD')||input.LA(1)=='\u0BD7'||(input.LA(1) >= '\u0BE7' && input.LA(1) <= '\u0BFA')||(input.LA(1) >= '\u0C01' && input.LA(1) <= '\u0C03')||(input.LA(1) >= '\u0C05' && input.LA(1) <= '\u0C0C')||(input.LA(1) >= '\u0C0E' && input.LA(1) <= '\u0C10')||(input.LA(1) >= '\u0C12' && input.LA(1) <= '\u0C28')||(input.LA(1) >= '\u0C2A' && input.LA(1) <= '\u0C33')||(input.LA(1) >= '\u0C35' && input.LA(1) <= '\u0C39')||(input.LA(1) >= '\u0C3E' && input.LA(1) <= '\u0C44')||(input.LA(1) >= '\u0C46' && input.LA(1) <= '\u0C48')||(input.LA(1) >= '\u0C4A' && input.LA(1) <= '\u0C4D')||(input.LA(1) >= '\u0C55' && input.LA(1) <= '\u0C56')||(input.LA(1) >= '\u0C60' && input.LA(1) <= '\u0C61')||(input.LA(1) >= '\u0C66' && input.LA(1) <= '\u0C6F')||(input.LA(1) >= '\u0C82' && input.LA(1) <= '\u0C83')||(input.LA(1) >= '\u0C85' && input.LA(1) <= '\u0C8C')||(input.LA(1) >= '\u0C8E' && input.LA(1) <= '\u0C90')||(input.LA(1) >= '\u0C92' && input.LA(1) <= '\u0CA8')||(input.LA(1) >= '\u0CAA' && input.LA(1) <= '\u0CB3')||(input.LA(1) >= '\u0CB5' && input.LA(1) <= '\u0CB9')||(input.LA(1) >= '\u0CBC' && input.LA(1) <= '\u0CC4')||(input.LA(1) >= '\u0CC6' && input.LA(1) <= '\u0CC8')||(input.LA(1) >= '\u0CCA' && input.LA(1) <= '\u0CCD')||(input.LA(1) >= '\u0CD5' && input.LA(1) <= '\u0CD6')||input.LA(1)=='\u0CDE'||(input.LA(1) >= '\u0CE0' && input.LA(1) <= '\u0CE1')||(input.LA(1) >= '\u0CE6' && input.LA(1) <= '\u0CEF')||(input.LA(1) >= '\u0D02' && input.LA(1) <= '\u0D03')||(input.LA(1) >= '\u0D05' && input.LA(1) <= '\u0D0C')||(input.LA(1) >= '\u0D0E' && input.LA(1) <= '\u0D10')||(input.LA(1) >= '\u0D12' && input.LA(1) <= '\u0D28')||(input.LA(1) >= '\u0D2A' && input.LA(1) <= '\u0D39')||(input.LA(1) >= '\u0D3E' && input.LA(1) <= '\u0D43')||(input.LA(1) >= '\u0D46' && input.LA(1) <= '\u0D48')||(input.LA(1) >= '\u0D4A' && input.LA(1) <= '\u0D4D')||input.LA(1)=='\u0D57'||(input.LA(1) >= '\u0D60' && input.LA(1) <= '\u0D61')||(input.LA(1) >= '\u0D66' && input.LA(1) <= '\u0D6F')||(input.LA(1) >= '\u0D82' && input.LA(1) <= '\u0D83')||(input.LA(1) >= '\u0D85' && input.LA(1) <= '\u0D96')||(input.LA(1) >= '\u0D9A' && input.LA(1) <= '\u0DB1')||(input.LA(1) >= '\u0DB3' && input.LA(1) <= '\u0DBB')||input.LA(1)=='\u0DBD'||(input.LA(1) >= '\u0DC0' && input.LA(1) <= '\u0DC6')||input.LA(1)=='\u0DCA'||(input.LA(1) >= '\u0DCF' && input.LA(1) <= '\u0DD4')||input.LA(1)=='\u0DD6'||(input.LA(1) >= '\u0DD8' && input.LA(1) <= '\u0DDF')||(input.LA(1) >= '\u0DF2' && input.LA(1) <= '\u0DF4')||(input.LA(1) >= '\u0E01' && input.LA(1) <= '\u0E3A')||(input.LA(1) >= '\u0E3F' && input.LA(1) <= '\u0E5B')||(input.LA(1) >= '\u0E81' && input.LA(1) <= '\u0E82')||input.LA(1)=='\u0E84'||(input.LA(1) >= '\u0E87' && input.LA(1) <= '\u0E88')||input.LA(1)=='\u0E8A'||input.LA(1)=='\u0E8D'||(input.LA(1) >= '\u0E94' && input.LA(1) <= '\u0E97')||(input.LA(1) >= '\u0E99' && input.LA(1) <= '\u0E9F')||(input.LA(1) >= '\u0EA1' && input.LA(1) <= '\u0EA3')||input.LA(1)=='\u0EA5'||input.LA(1)=='\u0EA7'||(input.LA(1) >= '\u0EAA' && input.LA(1) <= '\u0EAB')||(input.LA(1) >= '\u0EAD' && input.LA(1) <= '\u0EB9')||(input.LA(1) >= '\u0EBB' && input.LA(1) <= '\u0EBD')||(input.LA(1) >= '\u0EC0' && input.LA(1) <= '\u0EC4')||input.LA(1)=='\u0EC6'||(input.LA(1) >= '\u0EC8' && input.LA(1) <= '\u0ECD')||(input.LA(1) >= '\u0ED0' && input.LA(1) <= '\u0ED9')||(input.LA(1) >= '\u0EDC' && input.LA(1) <= '\u0EDD')||(input.LA(1) >= '\u0F00' && input.LA(1) <= '\u0F39')||(input.LA(1) >= '\u0F3E' && input.LA(1) <= '\u0F47')||(input.LA(1) >= '\u0F49' && input.LA(1) <= '\u0F6A')||(input.LA(1) >= '\u0F71' && input.LA(1) <= '\u0F8B')||(input.LA(1) >= '\u0F90' && input.LA(1) <= '\u0F97')||(input.LA(1) >= '\u0F99' && input.LA(1) <= '\u0FBC')||(input.LA(1) >= '\u0FBE' && input.LA(1) <= '\u0FCC')||input.LA(1)=='\u0FCF'||(input.LA(1) >= '\u1000' && input.LA(1) <= '\u1021')||(input.LA(1) >= '\u1023' && input.LA(1) <= '\u1027')||(input.LA(1) >= '\u1029' && input.LA(1) <= '\u102A')||(input.LA(1) >= '\u102C' && input.LA(1) <= '\u1032')||(input.LA(1) >= '\u1036' && input.LA(1) <= '\u1039')||(input.LA(1) >= '\u1040' && input.LA(1) <= '\u1059')||(input.LA(1) >= '\u10A0' && input.LA(1) <= '\u10C5')||(input.LA(1) >= '\u10D0' && input.LA(1) <= '\u10F8')||input.LA(1)=='\u10FB'||(input.LA(1) >= '\u1100' && input.LA(1) <= '\u1159')||(input.LA(1) >= '\u115F' && input.LA(1) <= '\u11A2')||(input.LA(1) >= '\u11A8' && input.LA(1) <= '\u11F9')||(input.LA(1) >= '\u1200' && input.LA(1) <= '\u1206')||(input.LA(1) >= '\u1208' && input.LA(1) <= '\u1246')||input.LA(1)=='\u1248'||(input.LA(1) >= '\u124A' && input.LA(1) <= '\u124D')||(input.LA(1) >= '\u1250' && input.LA(1) <= '\u1256')||input.LA(1)=='\u1258'||(input.LA(1) >= '\u125A' && input.LA(1) <= '\u125D')||(input.LA(1) >= '\u1260' && input.LA(1) <= '\u1286')||input.LA(1)=='\u1288'||(input.LA(1) >= '\u128A' && input.LA(1) <= '\u128D')||(input.LA(1) >= '\u1290' && input.LA(1) <= '\u12AE')||input.LA(1)=='\u12B0'||(input.LA(1) >= '\u12B2' && input.LA(1) <= '\u12B5')||(input.LA(1) >= '\u12B8' && input.LA(1) <= '\u12BE')||input.LA(1)=='\u12C0'||(input.LA(1) >= '\u12C2' && input.LA(1) <= '\u12C5')||(input.LA(1) >= '\u12C8' && input.LA(1) <= '\u12CE')||(input.LA(1) >= '\u12D0' && input.LA(1) <= '\u12D6')||(input.LA(1) >= '\u12D8' && input.LA(1) <= '\u12EE')||(input.LA(1) >= '\u12F0' && input.LA(1) <= '\u130E')||input.LA(1)=='\u1310'||(input.LA(1) >= '\u1312' && input.LA(1) <= '\u1315')||(input.LA(1) >= '\u1318' && input.LA(1) <= '\u131E')||(input.LA(1) >= '\u1320' && input.LA(1) <= '\u1346')||(input.LA(1) >= '\u1348' && input.LA(1) <= '\u135A')||(input.LA(1) >= '\u1361' && input.LA(1) <= '\u137C')||(input.LA(1) >= '\u13A0' && input.LA(1) <= '\u13F4')||(input.LA(1) >= '\u1401' && input.LA(1) <= '\u1676')||(input.LA(1) >= '\u1681' && input.LA(1) <= '\u169A')||(input.LA(1) >= '\u16A0' && input.LA(1) <= '\u16F0')||(input.LA(1) >= '\u1700' && input.LA(1) <= '\u170C')||(input.LA(1) >= '\u170E' && input.LA(1) <= '\u1714')||(input.LA(1) >= '\u1720' && input.LA(1) <= '\u1736')||(input.LA(1) >= '\u1740' && input.LA(1) <= '\u1753')||(input.LA(1) >= '\u1760' && input.LA(1) <= '\u176C')||(input.LA(1) >= '\u176E' && input.LA(1) <= '\u1770')||(input.LA(1) >= '\u1772' && input.LA(1) <= '\u1773')||(input.LA(1) >= '\u1780' && input.LA(1) <= '\u17B3')||(input.LA(1) >= '\u17B6' && input.LA(1) <= '\u17DD')||(input.LA(1) >= '\u17E0' && input.LA(1) <= '\u17E9')||(input.LA(1) >= '\u17F0' && input.LA(1) <= '\u17F9')||(input.LA(1) >= '\u1800' && input.LA(1) <= '\u180D')||(input.LA(1) >= '\u1810' && input.LA(1) <= '\u1819')||(input.LA(1) >= '\u1820' && input.LA(1) <= '\u1877')||(input.LA(1) >= '\u1880' && input.LA(1) <= '\u18A9')||(input.LA(1) >= '\u1900' && input.LA(1) <= '\u191C')||(input.LA(1) >= '\u1920' && input.LA(1) <= '\u192B')||(input.LA(1) >= '\u1930' && input.LA(1) <= '\u193B')||input.LA(1)=='\u1940'||(input.LA(1) >= '\u1944' && input.LA(1) <= '\u196D')||(input.LA(1) >= '\u1970' && input.LA(1) <= '\u1974')||(input.LA(1) >= '\u19E0' && input.LA(1) <= '\u19FF')||(input.LA(1) >= '\u1D00' && input.LA(1) <= '\u1D6B')||(input.LA(1) >= '\u1E00' && input.LA(1) <= '\u1E9B')||(input.LA(1) >= '\u1EA0' && input.LA(1) <= '\u1EF9')||(input.LA(1) >= '\u1F00' && input.LA(1) <= '\u1F15')||(input.LA(1) >= '\u1F18' && input.LA(1) <= '\u1F1D')||(input.LA(1) >= '\u1F20' && input.LA(1) <= '\u1F45')||(input.LA(1) >= '\u1F48' && input.LA(1) <= '\u1F4D')||(input.LA(1) >= '\u1F50' && input.LA(1) <= '\u1F57')||input.LA(1)=='\u1F59'||input.LA(1)=='\u1F5B'||input.LA(1)=='\u1F5D'||(input.LA(1) >= '\u1F5F' && input.LA(1) <= '\u1F7D')||(input.LA(1) >= '\u1F80' && input.LA(1) <= '\u1FB4')||(input.LA(1) >= '\u1FB6' && input.LA(1) <= '\u1FBC')||input.LA(1)=='\u1FBE'||(input.LA(1) >= '\u1FC2' && input.LA(1) <= '\u1FC4')||(input.LA(1) >= '\u1FC6' && input.LA(1) <= '\u1FCC')||(input.LA(1) >= '\u1FD0' && input.LA(1) <= '\u1FD3')||(input.LA(1) >= '\u1FD6' && input.LA(1) <= '\u1FDB')||(input.LA(1) >= '\u1FE0' && input.LA(1) <= '\u1FEC')||(input.LA(1) >= '\u1FF2' && input.LA(1) <= '\u1FF4')||(input.LA(1) >= '\u1FF6' && input.LA(1) <= '\u1FFC')||(input.LA(1) >= '\u2010' && input.LA(1) <= '\u2017')||(input.LA(1) >= '\u2020' && input.LA(1) <= '\u2027')||(input.LA(1) >= '\u2030' && input.LA(1) <= '\u2038')||(input.LA(1) >= '\u203B' && input.LA(1) <= '\u2044')||(input.LA(1) >= '\u2047' && input.LA(1) <= '\u2054')||input.LA(1)=='\u2057'||(input.LA(1) >= '\u2070' && input.LA(1) <= '\u2071')||(input.LA(1) >= '\u2074' && input.LA(1) <= '\u207C')||(input.LA(1) >= '\u207F' && input.LA(1) <= '\u208C')||(input.LA(1) >= '\u20A0' && input.LA(1) <= '\u20B1')||(input.LA(1) >= '\u20D0' && input.LA(1) <= '\u20EA')||(input.LA(1) >= '\u2100' && input.LA(1) <= '\u213B')||(input.LA(1) >= '\u213D' && input.LA(1) <= '\u214B')||(input.LA(1) >= '\u2153' && input.LA(1) <= '\u2183')||(input.LA(1) >= '\u2190' && input.LA(1) <= '\u2328')||(input.LA(1) >= '\u232B' && input.LA(1) <= '\u23B3')||(input.LA(1) >= '\u23B6' && input.LA(1) <= '\u23D0')||(input.LA(1) >= '\u2400' && input.LA(1) <= '\u2426')||(input.LA(1) >= '\u2440' && input.LA(1) <= '\u244A')||(input.LA(1) >= '\u2460' && input.LA(1) <= '\u2617')||(input.LA(1) >= '\u2619' && input.LA(1) <= '\u267D')||(input.LA(1) >= '\u2680' && input.LA(1) <= '\u2691')||(input.LA(1) >= '\u26A0' && input.LA(1) <= '\u26A1')||(input.LA(1) >= '\u2701' && input.LA(1) <= '\u2704')||(input.LA(1) >= '\u2706' && input.LA(1) <= '\u2709')||(input.LA(1) >= '\u270C' && input.LA(1) <= '\u2727')||(input.LA(1) >= '\u2729' && input.LA(1) <= '\u274B')||input.LA(1)=='\u274D'||(input.LA(1) >= '\u274F' && input.LA(1) <= '\u2752')||input.LA(1)=='\u2756'||(input.LA(1) >= '\u2758' && input.LA(1) <= '\u275E')||(input.LA(1) >= '\u2761' && input.LA(1) <= '\u2767')||(input.LA(1) >= '\u2776' && input.LA(1) <= '\u2794')||(input.LA(1) >= '\u2798' && input.LA(1) <= '\u27AF')||(input.LA(1) >= '\u27B1' && input.LA(1) <= '\u27BE')||(input.LA(1) >= '\u27D0' && input.LA(1) <= '\u27E5')||(input.LA(1) >= '\u27F0' && input.LA(1) <= '\u2982')||(input.LA(1) >= '\u2999' && input.LA(1) <= '\u29D7')||(input.LA(1) >= '\u29DC' && input.LA(1) <= '\u29FB')||(input.LA(1) >= '\u29FE' && input.LA(1) <= '\u2B0D')||(input.LA(1) >= '\u2E80' && input.LA(1) <= '\u2E99')||(input.LA(1) >= '\u2E9B' && input.LA(1) <= '\u2EF3')||(input.LA(1) >= '\u2F00' && input.LA(1) <= '\u2FD5')||(input.LA(1) >= '\u2FF0' && input.LA(1) <= '\u2FFB')||(input.LA(1) >= '\u3001' && input.LA(1) <= '\u3007')||(input.LA(1) >= '\u3012' && input.LA(1) <= '\u3013')||input.LA(1)=='\u301C'||(input.LA(1) >= '\u3020' && input.LA(1) <= '\u303F')||(input.LA(1) >= '\u3041' && input.LA(1) <= '\u3096')||(input.LA(1) >= '\u3099' && input.LA(1) <= '\u309A')||(input.LA(1) >= '\u309D' && input.LA(1) <= '\u30FF')||(input.LA(1) >= '\u3105' && input.LA(1) <= '\u312C')||(input.LA(1) >= '\u3131' && input.LA(1) <= '\u318E')||(input.LA(1) >= '\u3190' && input.LA(1) <= '\u31B7')||(input.LA(1) >= '\u31F0' && input.LA(1) <= '\u321E')||(input.LA(1) >= '\u3220' && input.LA(1) <= '\u3243')||(input.LA(1) >= '\u3250' && input.LA(1) <= '\u327D')||(input.LA(1) >= '\u327F' && input.LA(1) <= '\u32FE')||(input.LA(1) >= '\u3300' && input.LA(1) <= '\u4DB5')||(input.LA(1) >= '\u4DC0' && input.LA(1) <= '\u9FA5')||(input.LA(1) >= '\uA000' && input.LA(1) <= '\uA48C')||(input.LA(1) >= '\uA490' && input.LA(1) <= '\uA4C6')||(input.LA(1) >= '\uAC00' && input.LA(1) <= '\uD7A3')||(input.LA(1) >= '\uF900' && input.LA(1) <= '\uFA2D')||(input.LA(1) >= '\uFA30' && input.LA(1) <= '\uFA6A')||(input.LA(1) >= '\uFB00' && input.LA(1) <= '\uFB06')||(input.LA(1) >= '\uFB13' && input.LA(1) <= '\uFB17')||(input.LA(1) >= '\uFB1D' && input.LA(1) <= '\uFB36')||(input.LA(1) >= '\uFB38' && input.LA(1) <= '\uFB3C')||input.LA(1)=='\uFB3E'||(input.LA(1) >= '\uFB40' && input.LA(1) <= '\uFB41')||(input.LA(1) >= '\uFB43' && input.LA(1) <= '\uFB44')||(input.LA(1) >= '\uFB46' && input.LA(1) <= '\uFBB1')||(input.LA(1) >= '\uFBD3' && input.LA(1) <= '\uFD3D')||(input.LA(1) >= '\uFD50' && input.LA(1) <= '\uFD8F')||(input.LA(1) >= '\uFD92' && input.LA(1) <= '\uFDC7')||(input.LA(1) >= '\uFDF0' && input.LA(1) <= '\uFDFD')||(input.LA(1) >= '\uFE00' && input.LA(1) <= '\uFE0F')||(input.LA(1) >= '\uFE20' && input.LA(1) <= '\uFE23')||(input.LA(1) >= '\uFE30' && input.LA(1) <= '\uFE34')||(input.LA(1) >= '\uFE45' && input.LA(1) <= '\uFE46')||(input.LA(1) >= '\uFE49' && input.LA(1) <= '\uFE52')||(input.LA(1) >= '\uFE54' && input.LA(1) <= '\uFE58')||(input.LA(1) >= '\uFE5F' && input.LA(1) <= '\uFE66')||(input.LA(1) >= '\uFE68' && input.LA(1) <= '\uFE6B')||(input.LA(1) >= '\uFE70' && input.LA(1) <= '\uFE74')||(input.LA(1) >= '\uFE76' && input.LA(1) <= '\uFEFC')||(input.LA(1) >= '\uFF01' && input.LA(1) <= '\uFF07')||(input.LA(1) >= '\uFF0A' && input.LA(1) <= '\uFF3A')||input.LA(1)=='\uFF3C'||input.LA(1)=='\uFF3F'||(input.LA(1) >= '\uFF41' && input.LA(1) <= '\uFF5A')||input.LA(1)=='\uFF5C'||input.LA(1)=='\uFF5E'||input.LA(1)=='\uFF61'||(input.LA(1) >= '\uFF64' && input.LA(1) <= '\uFFBE')||(input.LA(1) >= '\uFFC2' && input.LA(1) <= '\uFFC7')||(input.LA(1) >= '\uFFCA' && input.LA(1) <= '\uFFCF')||(input.LA(1) >= '\uFFD2' && input.LA(1) <= '\uFFD7')||(input.LA(1) >= '\uFFDA' && input.LA(1) <= '\uFFDC')||(input.LA(1) >= '\uFFE0' && input.LA(1) <= '\uFFE2')||(input.LA(1) >= '\uFFE4' && input.LA(1) <= '\uFFE6')||(input.LA(1) >= '\uFFE8' && input.LA(1) <= '\uFFEE') ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "IN_WORD" + + // $ANTLR start "WS" + public final void mWS() throws RecognitionException { + try { + int _type = WS; + int _channel = DEFAULT_TOKEN_CHANNEL; + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:2401:9: ( ( ' ' | '\\t' | '\\r' | '\\n' | '\\u000C' | '\\u00a0' | '\\u1680' | '\\u180e' | '\\u2000' .. '\\u200b' | '\\u2028' .. '\\u2029' | '\\u202f' | '\\u205f' | '\\u3000' )+ ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:2402:9: ( ' ' | '\\t' | '\\r' | '\\n' | '\\u000C' | '\\u00a0' | '\\u1680' | '\\u180e' | '\\u2000' .. '\\u200b' | '\\u2028' .. '\\u2029' | '\\u202f' | '\\u205f' | '\\u3000' )+ + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:2402:9: ( ' ' | '\\t' | '\\r' | '\\n' | '\\u000C' | '\\u00a0' | '\\u1680' | '\\u180e' | '\\u2000' .. '\\u200b' | '\\u2028' .. '\\u2029' | '\\u202f' | '\\u205f' | '\\u3000' )+ + int cnt62=0; + loop62: + while (true) { + int alt62=2; + int LA62_0 = input.LA(1); + if ( ((LA62_0 >= '\t' && LA62_0 <= '\n')||(LA62_0 >= '\f' && LA62_0 <= '\r')||LA62_0==' '||LA62_0=='\u00A0'||LA62_0=='\u1680'||LA62_0=='\u180E'||(LA62_0 >= '\u2000' && LA62_0 <= '\u200B')||(LA62_0 >= '\u2028' && LA62_0 <= '\u2029')||LA62_0=='\u202F'||LA62_0=='\u205F'||LA62_0=='\u3000') ) { + alt62=1; + } + + switch (alt62) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( (input.LA(1) >= '\t' && input.LA(1) <= '\n')||(input.LA(1) >= '\f' && input.LA(1) <= '\r')||input.LA(1)==' '||input.LA(1)=='\u00A0'||input.LA(1)=='\u1680'||input.LA(1)=='\u180E'||(input.LA(1) >= '\u2000' && input.LA(1) <= '\u200B')||(input.LA(1) >= '\u2028' && input.LA(1) <= '\u2029')||input.LA(1)=='\u202F'||input.LA(1)=='\u205F'||input.LA(1)=='\u3000' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + break; + + default : + if ( cnt62 >= 1 ) break loop62; + if (state.backtracking>0) {state.failed=true; return;} + EarlyExitException eee = new EarlyExitException(62, input); + throw eee; + } + cnt62++; + } + + if ( state.backtracking==0 ) { _channel = HIDDEN; } + } + + state.type = _type; + state.channel = _channel; + } + finally { + // do for sure before leaving + } + } + // $ANTLR end "WS" + + @Override + public void mTokens() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:8: ( FTSPHRASE | URI | DATETIME | OR | AND | NOT | TILDA | LPAREN | RPAREN | PLUS | MINUS | COLON | STAR | AMP | EXCLAMATION | BAR | EQUALS | QUESTION_MARK | LCURL | RCURL | LSQUARE | RSQUARE | TO | COMMA | CARAT | DOLLAR | GT | LT | AT | PERCENT | ID | FLOATING_POINT_LITERAL | FTSWORD | FTSPRE | FTSWILD | WS ) + int alt63=36; + alt63 = dfa63.predict(input); + switch (alt63) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:10: FTSPHRASE + { + mFTSPHRASE(); if (state.failed) return; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:20: URI + { + mURI(); if (state.failed) return; + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:24: DATETIME + { + mDATETIME(); if (state.failed) return; + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:33: OR + { + mOR(); if (state.failed) return; + + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:36: AND + { + mAND(); if (state.failed) return; + + } + break; + case 6 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:40: NOT + { + mNOT(); if (state.failed) return; + + } + break; + case 7 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:44: TILDA + { + mTILDA(); if (state.failed) return; + + } + break; + case 8 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:50: LPAREN + { + mLPAREN(); if (state.failed) return; + + } + break; + case 9 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:57: RPAREN + { + mRPAREN(); if (state.failed) return; + + } + break; + case 10 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:64: PLUS + { + mPLUS(); if (state.failed) return; + + } + break; + case 11 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:69: MINUS + { + mMINUS(); if (state.failed) return; + + } + break; + case 12 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:75: COLON + { + mCOLON(); if (state.failed) return; + + } + break; + case 13 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:81: STAR + { + mSTAR(); if (state.failed) return; + + } + break; + case 14 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:86: AMP + { + mAMP(); if (state.failed) return; + + } + break; + case 15 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:90: EXCLAMATION + { + mEXCLAMATION(); if (state.failed) return; + + } + break; + case 16 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:102: BAR + { + mBAR(); if (state.failed) return; + + } + break; + case 17 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:106: EQUALS + { + mEQUALS(); if (state.failed) return; + + } + break; + case 18 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:113: QUESTION_MARK + { + mQUESTION_MARK(); if (state.failed) return; + + } + break; + case 19 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:127: LCURL + { + mLCURL(); if (state.failed) return; + + } + break; + case 20 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:133: RCURL + { + mRCURL(); if (state.failed) return; + + } + break; + case 21 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:139: LSQUARE + { + mLSQUARE(); if (state.failed) return; + + } + break; + case 22 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:147: RSQUARE + { + mRSQUARE(); if (state.failed) return; + + } + break; + case 23 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:155: TO + { + mTO(); if (state.failed) return; + + } + break; + case 24 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:158: COMMA + { + mCOMMA(); if (state.failed) return; + + } + break; + case 25 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:164: CARAT + { + mCARAT(); if (state.failed) return; + + } + break; + case 26 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:170: DOLLAR + { + mDOLLAR(); if (state.failed) return; + + } + break; + case 27 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:177: GT + { + mGT(); if (state.failed) return; + + } + break; + case 28 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:180: LT + { + mLT(); if (state.failed) return; + + } + break; + case 29 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:183: AT + { + mAT(); if (state.failed) return; + + } + break; + case 30 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:186: PERCENT + { + mPERCENT(); if (state.failed) return; + + } + break; + case 31 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:194: ID + { + mID(); if (state.failed) return; + + } + break; + case 32 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:197: FLOATING_POINT_LITERAL + { + mFLOATING_POINT_LITERAL(); if (state.failed) return; + + } + break; + case 33 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:220: FTSWORD + { + mFTSWORD(); if (state.failed) return; + + } + break; + case 34 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:228: FTSPRE + { + mFTSPRE(); if (state.failed) return; + + } + break; + case 35 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:235: FTSWILD + { + mFTSWILD(); if (state.failed) return; + + } + break; + case 36 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:1:243: WS + { + mWS(); if (state.failed) return; + + } + break; + + } + } + + // $ANTLR start synpred1_FTS + public final void synpred1_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:967:17: ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='!'||input.LA(1)=='$'||(input.LA(1) >= '&' && input.LA(1) <= '.')||(input.LA(1) >= '0' && input.LA(1) <= '9')||input.LA(1)==';'||input.LA(1)=='='||(input.LA(1) >= '@' && input.LA(1) <= '[')||input.LA(1)==']'||input.LA(1)=='_'||(input.LA(1) >= 'a' && input.LA(1) <= 'z')||input.LA(1)=='~' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + // $ANTLR end synpred1_FTS + + // $ANTLR start synpred2_FTS + public final void synpred2_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:981:19: ( '//' ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:981:20: '//' + { + match("//"); if (state.failed) return; + + } + + } + // $ANTLR end synpred2_FTS + + // $ANTLR start synpred3_FTS + public final void synpred3_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:983:25: ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER | COLON ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + if ( input.LA(1)=='!'||input.LA(1)=='$'||(input.LA(1) >= '&' && input.LA(1) <= '.')||(input.LA(1) >= '0' && input.LA(1) <= ';')||input.LA(1)=='='||(input.LA(1) >= '@' && input.LA(1) <= '[')||input.LA(1)==']'||input.LA(1)=='_'||(input.LA(1) >= 'a' && input.LA(1) <= 'z')||input.LA(1)=='~' ) { + input.consume(); + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + recover(mse); + throw mse; + } + } + + } + // $ANTLR end synpred3_FTS + + public final boolean synpred1_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred1_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred2_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred2_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred3_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred3_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + + + protected DFA5 dfa5 = new DFA5(this); + protected DFA63 dfa63 = new DFA63(this); + static final String DFA5_eotS = + "\5\uffff"; + static final String DFA5_eofS = + "\5\uffff"; + static final String DFA5_minS = + "\2\41\1\uffff\1\0\1\uffff"; + static final String DFA5_maxS = + "\2\176\1\uffff\1\0\1\uffff"; + static final String DFA5_acceptS = + "\2\uffff\1\2\1\uffff\1\1"; + static final String DFA5_specialS = + "\3\uffff\1\0\1\uffff}>"; + static final String[] DFA5_transitionS = { + "\1\1\1\uffff\1\2\1\1\1\uffff\11\1\1\2\12\1\1\2\1\1\1\uffff\1\1\1\uffff"+ + "\1\2\34\1\1\uffff\1\1\1\uffff\1\1\1\uffff\32\1\2\uffff\1\2\1\1", + "\1\1\1\uffff\1\2\1\1\1\uffff\11\1\1\2\12\1\1\3\1\1\1\uffff\1\1\1\uffff"+ + "\1\2\34\1\1\uffff\1\1\1\uffff\1\1\1\uffff\32\1\2\uffff\1\2\1\1", + "", + "\1\uffff", + "" + }; + + static final short[] DFA5_eot = DFA.unpackEncodedString(DFA5_eotS); + static final short[] DFA5_eof = DFA.unpackEncodedString(DFA5_eofS); + static final char[] DFA5_min = DFA.unpackEncodedStringToUnsignedChars(DFA5_minS); + static final char[] DFA5_max = DFA.unpackEncodedStringToUnsignedChars(DFA5_maxS); + static final short[] DFA5_accept = DFA.unpackEncodedString(DFA5_acceptS); + static final short[] DFA5_special = DFA.unpackEncodedString(DFA5_specialS); + static final short[][] DFA5_transition; + + static { + int numStates = DFA5_transitionS.length; + DFA5_transition = new short[numStates][]; + for (int i=0; i ( F_URI_ALPHA | F_URI_DIGIT | F_URI_OTHER )+ COLON )?"; + } + @Override + public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { + IntStream input = _input; + int _s = s; + switch ( s ) { + case 0 : + int LA5_3 = input.LA(1); + + int index5_3 = input.index(); + input.rewind(); + s = -1; + if ( (synpred1_FTS()) ) {s = 4;} + else if ( (true) ) {s = 2;} + + input.seek(index5_3); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 5, _s, input); + error(nvae); + throw nvae; + } + } + + static final String DFA63_eotS = + "\2\uffff\1\45\1\37\3\41\3\uffff\1\74\1\75\1\uffff\1\76\4\uffff\1\77\3"+ + "\uffff\1\41\2\uffff\1\102\4\uffff\1\41\3\uffff\1\106\3\uffff\1\37\2\106"+ + "\1\uffff\2\41\1\106\1\115\1\uffff\10\41\1\uffff\2\124\2\41\4\uffff\2\127"+ + "\2\uffff\2\106\1\uffff\1\37\3\106\1\41\1\106\1\uffff\1\137\1\142\1\137"+ + "\1\142\2\41\1\uffff\2\146\1\uffff\3\106\1\137\1\41\1\106\1\37\1\uffff"+ + "\2\106\1\uffff\3\41\1\uffff\3\106\1\37\4\41\7\106\3\41\3\106\4\41\14\106"+ + "\3\41\2\106\1\137\4\41\5\106\1\137\11\106\3\41\2\106\4\41\1\uffff\2\41"+ + "\1\137\3\106\3\137\5\106\1\137\4\106\2\41\2\137\1\106\2\137\1\106\1\137"+ + "\3\106\3\137\1\106\1\137\3\41\6\137\1\106\2\137\1\106\1\137\6\41\1\137"+ + "\1\106\5\137\1\106\6\41\1\106\1\137\1\106\2\137\6\41\4\106\1\137\1\106"+ + "\3\137"; + static final String DFA63_eofS = + "\u0109\uffff"; + static final String DFA63_minS = + "\1\11\1\uffff\5\41\3\uffff\2\56\1\uffff\1\41\4\uffff\1\41\3\uffff\1\41"+ + "\2\uffff\1\41\4\uffff\1\41\1\uffff\1\0\1\uffff\1\41\3\uffff\3\41\1\0\4"+ + "\41\1\uffff\10\41\1\0\4\41\4\uffff\2\41\1\uffff\1\0\2\41\1\uffff\6\41"+ + "\1\uffff\6\41\1\uffff\2\41\1\uffff\7\41\1\uffff\2\41\1\uffff\3\41\1\uffff"+ + "\107\41\1\0\132\41"; + static final String DFA63_maxS = + "\1\uffee\1\uffff\1\176\4\uffee\3\uffff\2\71\1\uffff\1\uffee\4\uffff\1"+ + "\uffee\3\uffff\1\uffee\2\uffff\1\uffee\4\uffff\1\uffee\1\uffff\1\uffff"+ + "\1\uffff\1\uffee\3\uffff\3\uffee\1\uffff\4\uffee\1\uffff\10\uffee\1\uffff"+ + "\4\uffee\4\uffff\2\uffee\1\uffff\1\uffff\2\uffee\1\uffff\6\uffee\1\uffff"+ + "\6\uffee\1\uffff\2\uffee\1\uffff\7\uffee\1\uffff\2\uffee\1\uffff\3\uffee"+ + "\1\uffff\107\uffee\1\uffff\132\uffee"; + static final String DFA63_acceptS = + "\1\uffff\1\1\5\uffff\1\7\1\10\1\11\2\uffff\1\14\1\uffff\1\16\1\17\1\20"+ + "\1\21\1\uffff\1\24\1\25\1\26\1\uffff\1\30\1\31\1\uffff\1\33\1\34\1\35"+ + "\1\36\1\uffff\1\40\1\uffff\1\37\1\uffff\1\44\1\2\1\23\10\uffff\1\43\15"+ + "\uffff\1\12\1\13\1\15\1\22\2\uffff\1\32\3\uffff\1\41\6\uffff\1\42\6\uffff"+ + "\1\4\2\uffff\1\27\7\uffff\1\3\2\uffff\1\6\3\uffff\1\5\u00a2\uffff"; + static final String DFA63_specialS = + "\40\uffff\1\3\10\uffff\1\0\15\uffff\1\1\13\uffff\1\4\152\uffff\1\2\132"+ + "\uffff}>"; + static final String[] DFA63_transitionS = { + "\2\43\1\uffff\2\43\22\uffff\1\43\1\17\1\1\1\uffff\1\31\1\35\1\16\1\1"+ + "\1\10\1\11\1\15\1\12\1\27\1\13\1\37\1\uffff\12\3\1\14\1\uffff\1\33\1"+ + "\21\1\32\1\22\1\34\1\6\14\36\1\4\1\5\4\36\1\26\6\36\1\24\1\40\1\25\1"+ + "\30\1\41\1\uffff\1\6\14\36\1\4\1\5\4\36\1\26\6\36\1\2\1\20\1\23\1\7\41"+ + "\uffff\1\43\1\uffff\6\42\1\uffff\2\42\3\uffff\1\42\1\uffff\1\42\1\uffff"+ + "\2\42\1\uffff\2\42\2\uffff\2\42\1\uffff\3\42\1\uffff\27\42\1\uffff\37"+ + "\42\1\uffff\u013f\42\31\uffff\162\42\4\uffff\14\42\16\uffff\5\42\11\uffff"+ + "\1\42\21\uffff\130\42\5\uffff\23\42\12\uffff\1\42\13\uffff\1\42\1\uffff"+ + "\3\42\1\uffff\1\42\1\uffff\24\42\1\uffff\54\42\1\uffff\46\42\1\uffff"+ + "\5\42\4\uffff\u0087\42\1\uffff\107\42\1\uffff\46\42\2\uffff\2\42\6\uffff"+ + "\20\42\41\uffff\46\42\2\uffff\1\42\7\uffff\47\42\11\uffff\21\42\1\uffff"+ + "\27\42\1\uffff\3\42\1\uffff\1\42\1\uffff\2\42\1\uffff\1\42\13\uffff\33"+ + "\42\5\uffff\3\42\33\uffff\10\42\13\uffff\32\42\5\uffff\31\42\7\uffff"+ + "\12\42\4\uffff\146\42\1\uffff\10\42\1\uffff\42\42\20\uffff\73\42\2\uffff"+ + "\3\42\60\uffff\62\42\u014f\uffff\71\42\2\uffff\22\42\2\uffff\5\42\3\uffff"+ + "\14\42\2\uffff\12\42\21\uffff\3\42\1\uffff\10\42\2\uffff\2\42\2\uffff"+ + "\26\42\1\uffff\7\42\1\uffff\1\42\3\uffff\4\42\2\uffff\11\42\2\uffff\2"+ + "\42\2\uffff\3\42\11\uffff\1\42\4\uffff\2\42\1\uffff\5\42\2\uffff\25\42"+ + "\6\uffff\3\42\1\uffff\6\42\4\uffff\2\42\2\uffff\26\42\1\uffff\7\42\1"+ + "\uffff\2\42\1\uffff\2\42\1\uffff\2\42\2\uffff\1\42\1\uffff\5\42\4\uffff"+ + "\2\42\2\uffff\3\42\13\uffff\4\42\1\uffff\1\42\7\uffff\17\42\14\uffff"+ + "\3\42\1\uffff\11\42\1\uffff\3\42\1\uffff\26\42\1\uffff\7\42\1\uffff\2"+ + "\42\1\uffff\5\42\2\uffff\12\42\1\uffff\3\42\1\uffff\3\42\2\uffff\1\42"+ + "\17\uffff\4\42\2\uffff\12\42\1\uffff\1\42\17\uffff\3\42\1\uffff\10\42"+ + "\2\uffff\2\42\2\uffff\26\42\1\uffff\7\42\1\uffff\2\42\1\uffff\5\42\2"+ + "\uffff\10\42\3\uffff\2\42\2\uffff\3\42\10\uffff\2\42\4\uffff\2\42\1\uffff"+ + "\3\42\4\uffff\14\42\20\uffff\2\42\1\uffff\6\42\3\uffff\3\42\1\uffff\4"+ + "\42\3\uffff\2\42\1\uffff\1\42\1\uffff\2\42\3\uffff\2\42\3\uffff\3\42"+ + "\3\uffff\10\42\1\uffff\3\42\4\uffff\5\42\3\uffff\3\42\1\uffff\4\42\11"+ + "\uffff\1\42\17\uffff\24\42\6\uffff\3\42\1\uffff\10\42\1\uffff\3\42\1"+ + "\uffff\27\42\1\uffff\12\42\1\uffff\5\42\4\uffff\7\42\1\uffff\3\42\1\uffff"+ + "\4\42\7\uffff\2\42\11\uffff\2\42\4\uffff\12\42\22\uffff\2\42\1\uffff"+ + "\10\42\1\uffff\3\42\1\uffff\27\42\1\uffff\12\42\1\uffff\5\42\2\uffff"+ + "\11\42\1\uffff\3\42\1\uffff\4\42\7\uffff\2\42\7\uffff\1\42\1\uffff\2"+ + "\42\4\uffff\12\42\22\uffff\2\42\1\uffff\10\42\1\uffff\3\42\1\uffff\27"+ + "\42\1\uffff\20\42\4\uffff\6\42\2\uffff\3\42\1\uffff\4\42\11\uffff\1\42"+ + "\10\uffff\2\42\4\uffff\12\42\22\uffff\2\42\1\uffff\22\42\3\uffff\30\42"+ + "\1\uffff\11\42\1\uffff\1\42\2\uffff\7\42\3\uffff\1\42\4\uffff\6\42\1"+ + "\uffff\1\42\1\uffff\10\42\22\uffff\2\42\15\uffff\72\42\4\uffff\20\42"+ + "\1\uffff\12\42\47\uffff\2\42\1\uffff\1\42\2\uffff\2\42\1\uffff\1\42\2"+ + "\uffff\1\42\6\uffff\4\42\1\uffff\7\42\1\uffff\3\42\1\uffff\1\42\1\uffff"+ + "\1\42\2\uffff\2\42\1\uffff\15\42\1\uffff\3\42\2\uffff\5\42\1\uffff\1"+ + "\42\1\uffff\6\42\2\uffff\12\42\2\uffff\2\42\42\uffff\4\42\17\uffff\47"+ + "\42\4\uffff\12\42\1\uffff\42\42\6\uffff\24\42\1\uffff\6\42\4\uffff\10"+ + "\42\1\uffff\44\42\1\uffff\17\42\2\uffff\1\42\60\uffff\42\42\1\uffff\5"+ + "\42\1\uffff\2\42\1\uffff\7\42\3\uffff\4\42\6\uffff\12\42\6\uffff\12\42"+ + "\106\uffff\46\42\12\uffff\51\42\7\uffff\132\42\5\uffff\104\42\5\uffff"+ + "\122\42\6\uffff\7\42\1\uffff\77\42\1\uffff\1\42\1\uffff\4\42\2\uffff"+ + "\7\42\1\uffff\1\42\1\uffff\4\42\2\uffff\47\42\1\uffff\1\42\1\uffff\4"+ + "\42\2\uffff\37\42\1\uffff\1\42\1\uffff\4\42\2\uffff\7\42\1\uffff\1\42"+ + "\1\uffff\4\42\2\uffff\7\42\1\uffff\7\42\1\uffff\27\42\1\uffff\37\42\1"+ + "\uffff\1\42\1\uffff\4\42\2\uffff\7\42\1\uffff\47\42\1\uffff\23\42\16"+ + "\uffff\24\42\43\uffff\125\42\14\uffff\u026c\42\2\uffff\10\42\11\uffff"+ + "\1\43\32\42\5\uffff\113\42\3\uffff\3\42\17\uffff\15\42\1\uffff\7\42\13"+ + "\uffff\25\42\13\uffff\24\42\14\uffff\15\42\1\uffff\3\42\1\uffff\2\42"+ + "\14\uffff\64\42\2\uffff\36\42\3\uffff\1\42\3\uffff\3\42\2\uffff\12\42"+ + "\6\uffff\12\42\21\uffff\3\42\1\43\1\uffff\12\42\6\uffff\130\42\10\uffff"+ + "\52\42\126\uffff\35\42\3\uffff\14\42\4\uffff\14\42\4\uffff\1\42\5\uffff"+ + "\50\42\2\uffff\5\42\153\uffff\40\42\u0300\uffff\154\42\u0094\uffff\u009c"+ + "\42\4\uffff\132\42\6\uffff\26\42\2\uffff\6\42\2\uffff\46\42\2\uffff\6"+ + "\42\2\uffff\10\42\1\uffff\1\42\1\uffff\1\42\1\uffff\1\42\1\uffff\37\42"+ + "\2\uffff\65\42\1\uffff\7\42\1\uffff\1\42\3\uffff\3\42\1\uffff\7\42\3"+ + "\uffff\4\42\2\uffff\6\42\4\uffff\15\42\5\uffff\3\42\1\uffff\7\42\3\uffff"+ + "\14\43\34\uffff\2\43\5\uffff\1\43\57\uffff\1\43\20\uffff\2\42\2\uffff"+ + "\6\42\5\uffff\13\42\26\uffff\22\42\36\uffff\33\42\25\uffff\74\42\1\uffff"+ + "\3\42\5\uffff\6\42\10\uffff\61\42\21\uffff\5\42\2\uffff\4\42\1\uffff"+ + "\2\42\1\uffff\2\42\1\uffff\7\42\1\uffff\37\42\2\uffff\2\42\1\uffff\1"+ + "\42\1\uffff\37\42\u010c\uffff\10\42\4\uffff\24\42\2\uffff\7\42\2\uffff"+ + "\121\42\1\uffff\36\42\34\uffff\32\42\57\uffff\47\42\31\uffff\13\42\25"+ + "\uffff\u0157\42\1\uffff\11\42\1\uffff\66\42\10\uffff\30\42\1\uffff\126"+ + "\42\1\uffff\16\42\2\uffff\22\42\16\uffff\2\42\137\uffff\4\42\1\uffff"+ + "\4\42\2\uffff\34\42\1\uffff\43\42\1\uffff\1\42\1\uffff\4\42\3\uffff\1"+ + "\42\1\uffff\7\42\2\uffff\7\42\16\uffff\37\42\3\uffff\30\42\1\uffff\16"+ + "\42\101\uffff\u0100\42\u0200\uffff\16\42\u0372\uffff\32\42\1\uffff\131"+ + "\42\14\uffff\u00d6\42\32\uffff\14\42\4\uffff\1\43\3\uffff\4\42\12\uffff"+ + "\2\42\14\uffff\20\42\1\uffff\14\42\1\uffff\2\42\1\uffff\126\42\2\uffff"+ + "\2\42\2\uffff\3\42\1\uffff\132\42\1\uffff\4\42\5\uffff\50\42\4\uffff"+ + "\136\42\1\uffff\50\42\70\uffff\57\42\1\uffff\44\42\14\uffff\56\42\1\uffff"+ + "\u0080\42\1\uffff\u1ab6\42\12\uffff\u51e6\42\132\uffff\u048d\42\3\uffff"+ + "\67\42\u0739\uffff\u2ba4\42\u215c\uffff\u012e\42\2\uffff\73\42\u0095"+ + "\uffff\7\42\14\uffff\5\42\5\uffff\14\42\1\uffff\15\42\1\uffff\5\42\1"+ + "\uffff\1\42\1\uffff\2\42\1\uffff\2\42\1\uffff\154\42\41\uffff\u016b\42"+ + "\22\uffff\100\42\2\uffff\66\42\50\uffff\16\42\2\uffff\20\42\20\uffff"+ + "\4\42\105\uffff\1\42\6\uffff\5\42\1\uffff\u0087\42\7\uffff\1\42\13\uffff"+ + "\12\42\7\uffff\32\42\6\uffff\32\42\13\uffff\131\42\3\uffff\6\42\2\uffff"+ + "\6\42\2\uffff\6\42\2\uffff\3\42\3\uffff\2\42\2\uffff\3\42\1\uffff\1\42"+ + "\4\uffff\2\42", + "", + "\1\44\1\uffff\2\44\1\uffff\26\44\1\uffff\1\44\1\uffff\35\44\1\uffff"+ + "\1\44\1\uffff\1\44\1\uffff\32\44\2\uffff\2\44", + "\2\54\1\50\1\47\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\46\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\4\53\1\52\25\53\1\uffff"+ + "\1\51\2\uffff\1\53\1\uffff\4\53\1\52\25\53\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\16\62\1\60\13\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\16\61\1\57\13\61\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\21\62\1\71\10\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\21\61\1\70\10\61\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\15\62\1\73\14\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\15\61\1\72\14\61\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "", + "", + "", + "\1\37\1\uffff\12\37", + "\1\37\1\uffff\12\37", + "", + "\7\56\2\uffff\2\56\1\uffff\1\56\1\uffff\13\56\1\uffff\1\56\1\uffff\1"+ + "\56\1\uffff\34\56\1\uffff\1\56\2\uffff\1\56\1\uffff\32\56\1\uffff\1\56"+ + "\44\uffff\7\56\1\uffff\2\56\1\uffff\1\56\1\uffff\1\56\1\uffff\4\56\1"+ + "\uffff\3\56\1\uffff\2\56\1\uffff\u017b\56\31\uffff\162\56\4\uffff\14"+ + "\56\16\uffff\5\56\11\uffff\1\56\21\uffff\130\56\5\uffff\23\56\12\uffff"+ + "\1\56\3\uffff\1\56\7\uffff\5\56\1\uffff\1\56\1\uffff\24\56\1\uffff\54"+ + "\56\1\uffff\54\56\4\uffff\u0087\56\1\uffff\107\56\1\uffff\46\56\2\uffff"+ + "\2\56\6\uffff\20\56\41\uffff\46\56\2\uffff\7\56\1\uffff\47\56\1\uffff"+ + "\2\56\6\uffff\21\56\1\uffff\27\56\1\uffff\12\56\13\uffff\33\56\5\uffff"+ + "\5\56\27\uffff\12\56\5\uffff\1\56\3\uffff\1\56\1\uffff\32\56\5\uffff"+ + "\31\56\7\uffff\175\56\1\uffff\60\56\2\uffff\73\56\2\uffff\3\56\60\uffff"+ + "\62\56\u014f\uffff\71\56\2\uffff\22\56\2\uffff\5\56\3\uffff\31\56\20"+ + "\uffff\3\56\1\uffff\10\56\2\uffff\2\56\2\uffff\26\56\1\uffff\7\56\1\uffff"+ + "\1\56\3\uffff\4\56\2\uffff\11\56\2\uffff\2\56\2\uffff\3\56\11\uffff\1"+ + "\56\4\uffff\2\56\1\uffff\5\56\2\uffff\25\56\6\uffff\3\56\1\uffff\6\56"+ + "\4\uffff\2\56\2\uffff\26\56\1\uffff\7\56\1\uffff\2\56\1\uffff\2\56\1"+ + "\uffff\2\56\2\uffff\1\56\1\uffff\5\56\4\uffff\2\56\2\uffff\3\56\13\uffff"+ + "\4\56\1\uffff\1\56\7\uffff\17\56\14\uffff\3\56\1\uffff\11\56\1\uffff"+ + "\3\56\1\uffff\26\56\1\uffff\7\56\1\uffff\2\56\1\uffff\5\56\2\uffff\12"+ + "\56\1\uffff\3\56\1\uffff\3\56\2\uffff\1\56\17\uffff\4\56\2\uffff\12\56"+ + "\1\uffff\1\56\17\uffff\3\56\1\uffff\10\56\2\uffff\2\56\2\uffff\26\56"+ + "\1\uffff\7\56\1\uffff\2\56\1\uffff\5\56\2\uffff\10\56\3\uffff\2\56\2"+ + "\uffff\3\56\10\uffff\2\56\4\uffff\2\56\1\uffff\3\56\4\uffff\14\56\20"+ + "\uffff\2\56\1\uffff\6\56\3\uffff\3\56\1\uffff\4\56\3\uffff\2\56\1\uffff"+ + "\1\56\1\uffff\2\56\3\uffff\2\56\3\uffff\3\56\3\uffff\10\56\1\uffff\3"+ + "\56\4\uffff\5\56\3\uffff\3\56\1\uffff\4\56\11\uffff\1\56\17\uffff\24"+ + "\56\6\uffff\3\56\1\uffff\10\56\1\uffff\3\56\1\uffff\27\56\1\uffff\12"+ + "\56\1\uffff\5\56\4\uffff\7\56\1\uffff\3\56\1\uffff\4\56\7\uffff\2\56"+ + "\11\uffff\2\56\4\uffff\12\56\22\uffff\2\56\1\uffff\10\56\1\uffff\3\56"+ + "\1\uffff\27\56\1\uffff\12\56\1\uffff\5\56\2\uffff\11\56\1\uffff\3\56"+ + "\1\uffff\4\56\7\uffff\2\56\7\uffff\1\56\1\uffff\2\56\4\uffff\12\56\22"+ + "\uffff\2\56\1\uffff\10\56\1\uffff\3\56\1\uffff\27\56\1\uffff\20\56\4"+ + "\uffff\6\56\2\uffff\3\56\1\uffff\4\56\11\uffff\1\56\10\uffff\2\56\4\uffff"+ + "\12\56\22\uffff\2\56\1\uffff\22\56\3\uffff\30\56\1\uffff\11\56\1\uffff"+ + "\1\56\2\uffff\7\56\3\uffff\1\56\4\uffff\6\56\1\uffff\1\56\1\uffff\10"+ + "\56\22\uffff\3\56\14\uffff\72\56\4\uffff\35\56\45\uffff\2\56\1\uffff"+ + "\1\56\2\uffff\2\56\1\uffff\1\56\2\uffff\1\56\6\uffff\4\56\1\uffff\7\56"+ + "\1\uffff\3\56\1\uffff\1\56\1\uffff\1\56\2\uffff\2\56\1\uffff\15\56\1"+ + "\uffff\3\56\2\uffff\5\56\1\uffff\1\56\1\uffff\6\56\2\uffff\12\56\2\uffff"+ + "\2\56\42\uffff\72\56\4\uffff\12\56\1\uffff\42\56\6\uffff\33\56\4\uffff"+ + "\10\56\1\uffff\44\56\1\uffff\17\56\2\uffff\1\56\60\uffff\42\56\1\uffff"+ + "\5\56\1\uffff\2\56\1\uffff\7\56\3\uffff\4\56\6\uffff\32\56\106\uffff"+ + "\46\56\12\uffff\51\56\2\uffff\1\56\4\uffff\132\56\5\uffff\104\56\5\uffff"+ + "\122\56\6\uffff\7\56\1\uffff\77\56\1\uffff\1\56\1\uffff\4\56\2\uffff"+ + "\7\56\1\uffff\1\56\1\uffff\4\56\2\uffff\47\56\1\uffff\1\56\1\uffff\4"+ + "\56\2\uffff\37\56\1\uffff\1\56\1\uffff\4\56\2\uffff\7\56\1\uffff\1\56"+ + "\1\uffff\4\56\2\uffff\7\56\1\uffff\7\56\1\uffff\27\56\1\uffff\37\56\1"+ + "\uffff\1\56\1\uffff\4\56\2\uffff\7\56\1\uffff\47\56\1\uffff\23\56\6\uffff"+ + "\34\56\43\uffff\125\56\14\uffff\u0276\56\12\uffff\32\56\5\uffff\121\56"+ + "\17\uffff\15\56\1\uffff\7\56\13\uffff\27\56\11\uffff\24\56\14\uffff\15"+ + "\56\1\uffff\3\56\1\uffff\2\56\14\uffff\64\56\2\uffff\50\56\2\uffff\12"+ + "\56\6\uffff\12\56\6\uffff\16\56\2\uffff\12\56\6\uffff\130\56\10\uffff"+ + "\52\56\126\uffff\35\56\3\uffff\14\56\4\uffff\14\56\4\uffff\1\56\3\uffff"+ + "\52\56\2\uffff\5\56\153\uffff\40\56\u0300\uffff\154\56\u0094\uffff\u009c"+ + "\56\4\uffff\132\56\6\uffff\26\56\2\uffff\6\56\2\uffff\46\56\2\uffff\6"+ + "\56\2\uffff\10\56\1\uffff\1\56\1\uffff\1\56\1\uffff\1\56\1\uffff\37\56"+ + "\2\uffff\65\56\1\uffff\7\56\1\uffff\1\56\3\uffff\3\56\1\uffff\7\56\3"+ + "\uffff\4\56\2\uffff\6\56\4\uffff\15\56\5\uffff\3\56\1\uffff\7\56\23\uffff"+ + "\10\56\10\uffff\10\56\10\uffff\11\56\2\uffff\12\56\2\uffff\16\56\2\uffff"+ + "\1\56\30\uffff\2\56\2\uffff\11\56\2\uffff\16\56\23\uffff\22\56\36\uffff"+ + "\33\56\25\uffff\74\56\1\uffff\17\56\7\uffff\61\56\14\uffff\u0199\56\2"+ + "\uffff\u0089\56\2\uffff\33\56\57\uffff\47\56\31\uffff\13\56\25\uffff"+ + "\u01b8\56\1\uffff\145\56\2\uffff\22\56\16\uffff\2\56\137\uffff\4\56\1"+ + "\uffff\4\56\2\uffff\34\56\1\uffff\43\56\1\uffff\1\56\1\uffff\4\56\3\uffff"+ + "\1\56\1\uffff\7\56\2\uffff\7\56\16\uffff\37\56\3\uffff\30\56\1\uffff"+ + "\16\56\21\uffff\26\56\12\uffff\u0193\56\26\uffff\77\56\4\uffff\40\56"+ + "\2\uffff\u0110\56\u0372\uffff\32\56\1\uffff\131\56\14\uffff\u00d6\56"+ + "\32\uffff\14\56\5\uffff\7\56\12\uffff\2\56\10\uffff\1\56\3\uffff\40\56"+ + "\1\uffff\126\56\2\uffff\2\56\2\uffff\143\56\5\uffff\50\56\4\uffff\136"+ + "\56\1\uffff\50\56\70\uffff\57\56\1\uffff\44\56\14\uffff\56\56\1\uffff"+ + "\u0080\56\1\uffff\u1ab6\56\12\uffff\u51e6\56\132\uffff\u048d\56\3\uffff"+ + "\67\56\u0739\uffff\u2ba4\56\u215c\uffff\u012e\56\2\uffff\73\56\u0095"+ + "\uffff\7\56\14\uffff\5\56\5\uffff\32\56\1\uffff\5\56\1\uffff\1\56\1\uffff"+ + "\2\56\1\uffff\2\56\1\uffff\154\56\41\uffff\u016b\56\22\uffff\100\56\2"+ + "\uffff\66\56\50\uffff\16\56\2\uffff\20\56\20\uffff\4\56\14\uffff\5\56"+ + "\20\uffff\2\56\2\uffff\12\56\1\uffff\5\56\6\uffff\10\56\1\uffff\4\56"+ + "\4\uffff\5\56\1\uffff\u0087\56\4\uffff\7\56\2\uffff\61\56\1\uffff\1\56"+ + "\2\uffff\1\56\1\uffff\32\56\1\uffff\1\56\1\uffff\1\56\2\uffff\1\56\2"+ + "\uffff\133\56\3\uffff\6\56\2\uffff\6\56\2\uffff\6\56\2\uffff\3\56\3\uffff"+ + "\3\56\1\uffff\3\56\1\uffff\7\56", + "", + "", + "", + "", + "\7\56\2\uffff\2\56\1\uffff\1\56\1\uffff\13\56\1\uffff\1\56\1\uffff\1"+ + "\56\1\uffff\34\56\1\uffff\1\56\2\uffff\1\56\1\uffff\32\56\1\uffff\1\56"+ + "\44\uffff\7\56\1\uffff\2\56\1\uffff\1\56\1\uffff\1\56\1\uffff\4\56\1"+ + "\uffff\3\56\1\uffff\2\56\1\uffff\u017b\56\31\uffff\162\56\4\uffff\14"+ + "\56\16\uffff\5\56\11\uffff\1\56\21\uffff\130\56\5\uffff\23\56\12\uffff"+ + "\1\56\3\uffff\1\56\7\uffff\5\56\1\uffff\1\56\1\uffff\24\56\1\uffff\54"+ + "\56\1\uffff\54\56\4\uffff\u0087\56\1\uffff\107\56\1\uffff\46\56\2\uffff"+ + "\2\56\6\uffff\20\56\41\uffff\46\56\2\uffff\7\56\1\uffff\47\56\1\uffff"+ + "\2\56\6\uffff\21\56\1\uffff\27\56\1\uffff\12\56\13\uffff\33\56\5\uffff"+ + "\5\56\27\uffff\12\56\5\uffff\1\56\3\uffff\1\56\1\uffff\32\56\5\uffff"+ + "\31\56\7\uffff\175\56\1\uffff\60\56\2\uffff\73\56\2\uffff\3\56\60\uffff"+ + "\62\56\u014f\uffff\71\56\2\uffff\22\56\2\uffff\5\56\3\uffff\31\56\20"+ + "\uffff\3\56\1\uffff\10\56\2\uffff\2\56\2\uffff\26\56\1\uffff\7\56\1\uffff"+ + "\1\56\3\uffff\4\56\2\uffff\11\56\2\uffff\2\56\2\uffff\3\56\11\uffff\1"+ + "\56\4\uffff\2\56\1\uffff\5\56\2\uffff\25\56\6\uffff\3\56\1\uffff\6\56"+ + "\4\uffff\2\56\2\uffff\26\56\1\uffff\7\56\1\uffff\2\56\1\uffff\2\56\1"+ + "\uffff\2\56\2\uffff\1\56\1\uffff\5\56\4\uffff\2\56\2\uffff\3\56\13\uffff"+ + "\4\56\1\uffff\1\56\7\uffff\17\56\14\uffff\3\56\1\uffff\11\56\1\uffff"+ + "\3\56\1\uffff\26\56\1\uffff\7\56\1\uffff\2\56\1\uffff\5\56\2\uffff\12"+ + "\56\1\uffff\3\56\1\uffff\3\56\2\uffff\1\56\17\uffff\4\56\2\uffff\12\56"+ + "\1\uffff\1\56\17\uffff\3\56\1\uffff\10\56\2\uffff\2\56\2\uffff\26\56"+ + "\1\uffff\7\56\1\uffff\2\56\1\uffff\5\56\2\uffff\10\56\3\uffff\2\56\2"+ + "\uffff\3\56\10\uffff\2\56\4\uffff\2\56\1\uffff\3\56\4\uffff\14\56\20"+ + "\uffff\2\56\1\uffff\6\56\3\uffff\3\56\1\uffff\4\56\3\uffff\2\56\1\uffff"+ + "\1\56\1\uffff\2\56\3\uffff\2\56\3\uffff\3\56\3\uffff\10\56\1\uffff\3"+ + "\56\4\uffff\5\56\3\uffff\3\56\1\uffff\4\56\11\uffff\1\56\17\uffff\24"+ + "\56\6\uffff\3\56\1\uffff\10\56\1\uffff\3\56\1\uffff\27\56\1\uffff\12"+ + "\56\1\uffff\5\56\4\uffff\7\56\1\uffff\3\56\1\uffff\4\56\7\uffff\2\56"+ + "\11\uffff\2\56\4\uffff\12\56\22\uffff\2\56\1\uffff\10\56\1\uffff\3\56"+ + "\1\uffff\27\56\1\uffff\12\56\1\uffff\5\56\2\uffff\11\56\1\uffff\3\56"+ + "\1\uffff\4\56\7\uffff\2\56\7\uffff\1\56\1\uffff\2\56\4\uffff\12\56\22"+ + "\uffff\2\56\1\uffff\10\56\1\uffff\3\56\1\uffff\27\56\1\uffff\20\56\4"+ + "\uffff\6\56\2\uffff\3\56\1\uffff\4\56\11\uffff\1\56\10\uffff\2\56\4\uffff"+ + "\12\56\22\uffff\2\56\1\uffff\22\56\3\uffff\30\56\1\uffff\11\56\1\uffff"+ + "\1\56\2\uffff\7\56\3\uffff\1\56\4\uffff\6\56\1\uffff\1\56\1\uffff\10"+ + "\56\22\uffff\3\56\14\uffff\72\56\4\uffff\35\56\45\uffff\2\56\1\uffff"+ + "\1\56\2\uffff\2\56\1\uffff\1\56\2\uffff\1\56\6\uffff\4\56\1\uffff\7\56"+ + "\1\uffff\3\56\1\uffff\1\56\1\uffff\1\56\2\uffff\2\56\1\uffff\15\56\1"+ + "\uffff\3\56\2\uffff\5\56\1\uffff\1\56\1\uffff\6\56\2\uffff\12\56\2\uffff"+ + "\2\56\42\uffff\72\56\4\uffff\12\56\1\uffff\42\56\6\uffff\33\56\4\uffff"+ + "\10\56\1\uffff\44\56\1\uffff\17\56\2\uffff\1\56\60\uffff\42\56\1\uffff"+ + "\5\56\1\uffff\2\56\1\uffff\7\56\3\uffff\4\56\6\uffff\32\56\106\uffff"+ + "\46\56\12\uffff\51\56\2\uffff\1\56\4\uffff\132\56\5\uffff\104\56\5\uffff"+ + "\122\56\6\uffff\7\56\1\uffff\77\56\1\uffff\1\56\1\uffff\4\56\2\uffff"+ + "\7\56\1\uffff\1\56\1\uffff\4\56\2\uffff\47\56\1\uffff\1\56\1\uffff\4"+ + "\56\2\uffff\37\56\1\uffff\1\56\1\uffff\4\56\2\uffff\7\56\1\uffff\1\56"+ + "\1\uffff\4\56\2\uffff\7\56\1\uffff\7\56\1\uffff\27\56\1\uffff\37\56\1"+ + "\uffff\1\56\1\uffff\4\56\2\uffff\7\56\1\uffff\47\56\1\uffff\23\56\6\uffff"+ + "\34\56\43\uffff\125\56\14\uffff\u0276\56\12\uffff\32\56\5\uffff\121\56"+ + "\17\uffff\15\56\1\uffff\7\56\13\uffff\27\56\11\uffff\24\56\14\uffff\15"+ + "\56\1\uffff\3\56\1\uffff\2\56\14\uffff\64\56\2\uffff\50\56\2\uffff\12"+ + "\56\6\uffff\12\56\6\uffff\16\56\2\uffff\12\56\6\uffff\130\56\10\uffff"+ + "\52\56\126\uffff\35\56\3\uffff\14\56\4\uffff\14\56\4\uffff\1\56\3\uffff"+ + "\52\56\2\uffff\5\56\153\uffff\40\56\u0300\uffff\154\56\u0094\uffff\u009c"+ + "\56\4\uffff\132\56\6\uffff\26\56\2\uffff\6\56\2\uffff\46\56\2\uffff\6"+ + "\56\2\uffff\10\56\1\uffff\1\56\1\uffff\1\56\1\uffff\1\56\1\uffff\37\56"+ + "\2\uffff\65\56\1\uffff\7\56\1\uffff\1\56\3\uffff\3\56\1\uffff\7\56\3"+ + "\uffff\4\56\2\uffff\6\56\4\uffff\15\56\5\uffff\3\56\1\uffff\7\56\23\uffff"+ + "\10\56\10\uffff\10\56\10\uffff\11\56\2\uffff\12\56\2\uffff\16\56\2\uffff"+ + "\1\56\30\uffff\2\56\2\uffff\11\56\2\uffff\16\56\23\uffff\22\56\36\uffff"+ + "\33\56\25\uffff\74\56\1\uffff\17\56\7\uffff\61\56\14\uffff\u0199\56\2"+ + "\uffff\u0089\56\2\uffff\33\56\57\uffff\47\56\31\uffff\13\56\25\uffff"+ + "\u01b8\56\1\uffff\145\56\2\uffff\22\56\16\uffff\2\56\137\uffff\4\56\1"+ + "\uffff\4\56\2\uffff\34\56\1\uffff\43\56\1\uffff\1\56\1\uffff\4\56\3\uffff"+ + "\1\56\1\uffff\7\56\2\uffff\7\56\16\uffff\37\56\3\uffff\30\56\1\uffff"+ + "\16\56\21\uffff\26\56\12\uffff\u0193\56\26\uffff\77\56\4\uffff\40\56"+ + "\2\uffff\u0110\56\u0372\uffff\32\56\1\uffff\131\56\14\uffff\u00d6\56"+ + "\32\uffff\14\56\5\uffff\7\56\12\uffff\2\56\10\uffff\1\56\3\uffff\40\56"+ + "\1\uffff\126\56\2\uffff\2\56\2\uffff\143\56\5\uffff\50\56\4\uffff\136"+ + "\56\1\uffff\50\56\70\uffff\57\56\1\uffff\44\56\14\uffff\56\56\1\uffff"+ + "\u0080\56\1\uffff\u1ab6\56\12\uffff\u51e6\56\132\uffff\u048d\56\3\uffff"+ + "\67\56\u0739\uffff\u2ba4\56\u215c\uffff\u012e\56\2\uffff\73\56\u0095"+ + "\uffff\7\56\14\uffff\5\56\5\uffff\32\56\1\uffff\5\56\1\uffff\1\56\1\uffff"+ + "\2\56\1\uffff\2\56\1\uffff\154\56\41\uffff\u016b\56\22\uffff\100\56\2"+ + "\uffff\66\56\50\uffff\16\56\2\uffff\20\56\20\uffff\4\56\14\uffff\5\56"+ + "\20\uffff\2\56\2\uffff\12\56\1\uffff\5\56\6\uffff\10\56\1\uffff\4\56"+ + "\4\uffff\5\56\1\uffff\u0087\56\4\uffff\7\56\2\uffff\61\56\1\uffff\1\56"+ + "\2\uffff\1\56\1\uffff\32\56\1\uffff\1\56\1\uffff\1\56\2\uffff\1\56\2"+ + "\uffff\133\56\3\uffff\6\56\2\uffff\6\56\2\uffff\6\56\2\uffff\3\56\3\uffff"+ + "\3\56\1\uffff\3\56\1\uffff\7\56", + "", + "", + "", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\16\62\1\101\13\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\16\61\1\100\13\61\1\uffff\1\54\44\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54"+ + "\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff"+ + "\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff"+ + "\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54"+ + "\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff"+ + "\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff"+ + "\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "", + "", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32\54\1\uffff"+ + "\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4"+ + "\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff"+ + "\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff"+ + "\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54"+ + "\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff"+ + "\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff"+ + "\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff"+ + "\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff"+ + "\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff"+ + "\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1"+ + "\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54"+ + "\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1"+ + "\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff"+ + "\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12"+ + "\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54"+ + "\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2"+ + "\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20"+ + "\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3"+ + "\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24"+ + "\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12"+ + "\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54"+ + "\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54"+ + "\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54"+ + "\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4"+ + "\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff"+ + "\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10"+ + "\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "", + "", + "", + "", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "", + "\165\105\1\104\uff8a\105", + "", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32\54\1\uffff"+ + "\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4"+ + "\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff"+ + "\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff"+ + "\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54"+ + "\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff"+ + "\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff"+ + "\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff"+ + "\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff"+ + "\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff"+ + "\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1"+ + "\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54"+ + "\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1"+ + "\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff"+ + "\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12"+ + "\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54"+ + "\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2"+ + "\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20"+ + "\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3"+ + "\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24"+ + "\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12"+ + "\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54"+ + "\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54"+ + "\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54"+ + "\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4"+ + "\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff"+ + "\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10"+ + "\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "", + "", + "", + "\2\54\1\50\1\47\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\107\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\4\53\1\52\25\53\1\uffff"+ + "\1\51\2\uffff\1\53\1\uffff\4\53\1\52\25\53\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\50\1\47\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\110\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\53\1\uffff\1\51\2"+ + "\uffff\1\53\1\uffff\32\53\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\50\1\47\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\110\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\53\1\uffff\1\51\2"+ + "\uffff\1\53\1\uffff\32\53\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\165\112\1\111\uff8a\112", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\114\1\uffff\1\114\1\uffff\1\54\12"+ + "\113\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32\54\1\uffff"+ + "\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4"+ + "\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff"+ + "\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff"+ + "\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54"+ + "\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff"+ + "\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff"+ + "\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff"+ + "\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff"+ + "\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff"+ + "\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1"+ + "\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54"+ + "\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1"+ + "\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff"+ + "\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12"+ + "\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54"+ + "\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2"+ + "\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20"+ + "\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3"+ + "\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24"+ + "\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12"+ + "\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54"+ + "\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54"+ + "\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54"+ + "\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4"+ + "\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff"+ + "\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10"+ + "\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\56\2\uffff\2\56\1\uffff\1\56\1\uffff\13\56\1\uffff\1\56\1\uffff\1"+ + "\56\1\uffff\34\56\1\uffff\1\56\2\uffff\1\56\1\uffff\32\56\1\uffff\1\56"+ + "\44\uffff\7\56\1\uffff\2\56\1\uffff\1\56\1\uffff\1\56\1\uffff\4\56\1"+ + "\uffff\3\56\1\uffff\2\56\1\uffff\u017b\56\31\uffff\162\56\4\uffff\14"+ + "\56\16\uffff\5\56\11\uffff\1\56\21\uffff\130\56\5\uffff\23\56\12\uffff"+ + "\1\56\3\uffff\1\56\7\uffff\5\56\1\uffff\1\56\1\uffff\24\56\1\uffff\54"+ + "\56\1\uffff\54\56\4\uffff\u0087\56\1\uffff\107\56\1\uffff\46\56\2\uffff"+ + "\2\56\6\uffff\20\56\41\uffff\46\56\2\uffff\7\56\1\uffff\47\56\1\uffff"+ + "\2\56\6\uffff\21\56\1\uffff\27\56\1\uffff\12\56\13\uffff\33\56\5\uffff"+ + "\5\56\27\uffff\12\56\5\uffff\1\56\3\uffff\1\56\1\uffff\32\56\5\uffff"+ + "\31\56\7\uffff\175\56\1\uffff\60\56\2\uffff\73\56\2\uffff\3\56\60\uffff"+ + "\62\56\u014f\uffff\71\56\2\uffff\22\56\2\uffff\5\56\3\uffff\31\56\20"+ + "\uffff\3\56\1\uffff\10\56\2\uffff\2\56\2\uffff\26\56\1\uffff\7\56\1\uffff"+ + "\1\56\3\uffff\4\56\2\uffff\11\56\2\uffff\2\56\2\uffff\3\56\11\uffff\1"+ + "\56\4\uffff\2\56\1\uffff\5\56\2\uffff\25\56\6\uffff\3\56\1\uffff\6\56"+ + "\4\uffff\2\56\2\uffff\26\56\1\uffff\7\56\1\uffff\2\56\1\uffff\2\56\1"+ + "\uffff\2\56\2\uffff\1\56\1\uffff\5\56\4\uffff\2\56\2\uffff\3\56\13\uffff"+ + "\4\56\1\uffff\1\56\7\uffff\17\56\14\uffff\3\56\1\uffff\11\56\1\uffff"+ + "\3\56\1\uffff\26\56\1\uffff\7\56\1\uffff\2\56\1\uffff\5\56\2\uffff\12"+ + "\56\1\uffff\3\56\1\uffff\3\56\2\uffff\1\56\17\uffff\4\56\2\uffff\12\56"+ + "\1\uffff\1\56\17\uffff\3\56\1\uffff\10\56\2\uffff\2\56\2\uffff\26\56"+ + "\1\uffff\7\56\1\uffff\2\56\1\uffff\5\56\2\uffff\10\56\3\uffff\2\56\2"+ + "\uffff\3\56\10\uffff\2\56\4\uffff\2\56\1\uffff\3\56\4\uffff\14\56\20"+ + "\uffff\2\56\1\uffff\6\56\3\uffff\3\56\1\uffff\4\56\3\uffff\2\56\1\uffff"+ + "\1\56\1\uffff\2\56\3\uffff\2\56\3\uffff\3\56\3\uffff\10\56\1\uffff\3"+ + "\56\4\uffff\5\56\3\uffff\3\56\1\uffff\4\56\11\uffff\1\56\17\uffff\24"+ + "\56\6\uffff\3\56\1\uffff\10\56\1\uffff\3\56\1\uffff\27\56\1\uffff\12"+ + "\56\1\uffff\5\56\4\uffff\7\56\1\uffff\3\56\1\uffff\4\56\7\uffff\2\56"+ + "\11\uffff\2\56\4\uffff\12\56\22\uffff\2\56\1\uffff\10\56\1\uffff\3\56"+ + "\1\uffff\27\56\1\uffff\12\56\1\uffff\5\56\2\uffff\11\56\1\uffff\3\56"+ + "\1\uffff\4\56\7\uffff\2\56\7\uffff\1\56\1\uffff\2\56\4\uffff\12\56\22"+ + "\uffff\2\56\1\uffff\10\56\1\uffff\3\56\1\uffff\27\56\1\uffff\20\56\4"+ + "\uffff\6\56\2\uffff\3\56\1\uffff\4\56\11\uffff\1\56\10\uffff\2\56\4\uffff"+ + "\12\56\22\uffff\2\56\1\uffff\22\56\3\uffff\30\56\1\uffff\11\56\1\uffff"+ + "\1\56\2\uffff\7\56\3\uffff\1\56\4\uffff\6\56\1\uffff\1\56\1\uffff\10"+ + "\56\22\uffff\3\56\14\uffff\72\56\4\uffff\35\56\45\uffff\2\56\1\uffff"+ + "\1\56\2\uffff\2\56\1\uffff\1\56\2\uffff\1\56\6\uffff\4\56\1\uffff\7\56"+ + "\1\uffff\3\56\1\uffff\1\56\1\uffff\1\56\2\uffff\2\56\1\uffff\15\56\1"+ + "\uffff\3\56\2\uffff\5\56\1\uffff\1\56\1\uffff\6\56\2\uffff\12\56\2\uffff"+ + "\2\56\42\uffff\72\56\4\uffff\12\56\1\uffff\42\56\6\uffff\33\56\4\uffff"+ + "\10\56\1\uffff\44\56\1\uffff\17\56\2\uffff\1\56\60\uffff\42\56\1\uffff"+ + "\5\56\1\uffff\2\56\1\uffff\7\56\3\uffff\4\56\6\uffff\32\56\106\uffff"+ + "\46\56\12\uffff\51\56\2\uffff\1\56\4\uffff\132\56\5\uffff\104\56\5\uffff"+ + "\122\56\6\uffff\7\56\1\uffff\77\56\1\uffff\1\56\1\uffff\4\56\2\uffff"+ + "\7\56\1\uffff\1\56\1\uffff\4\56\2\uffff\47\56\1\uffff\1\56\1\uffff\4"+ + "\56\2\uffff\37\56\1\uffff\1\56\1\uffff\4\56\2\uffff\7\56\1\uffff\1\56"+ + "\1\uffff\4\56\2\uffff\7\56\1\uffff\7\56\1\uffff\27\56\1\uffff\37\56\1"+ + "\uffff\1\56\1\uffff\4\56\2\uffff\7\56\1\uffff\47\56\1\uffff\23\56\6\uffff"+ + "\34\56\43\uffff\125\56\14\uffff\u0276\56\12\uffff\32\56\5\uffff\121\56"+ + "\17\uffff\15\56\1\uffff\7\56\13\uffff\27\56\11\uffff\24\56\14\uffff\15"+ + "\56\1\uffff\3\56\1\uffff\2\56\14\uffff\64\56\2\uffff\50\56\2\uffff\12"+ + "\56\6\uffff\12\56\6\uffff\16\56\2\uffff\12\56\6\uffff\130\56\10\uffff"+ + "\52\56\126\uffff\35\56\3\uffff\14\56\4\uffff\14\56\4\uffff\1\56\3\uffff"+ + "\52\56\2\uffff\5\56\153\uffff\40\56\u0300\uffff\154\56\u0094\uffff\u009c"+ + "\56\4\uffff\132\56\6\uffff\26\56\2\uffff\6\56\2\uffff\46\56\2\uffff\6"+ + "\56\2\uffff\10\56\1\uffff\1\56\1\uffff\1\56\1\uffff\1\56\1\uffff\37\56"+ + "\2\uffff\65\56\1\uffff\7\56\1\uffff\1\56\3\uffff\3\56\1\uffff\7\56\3"+ + "\uffff\4\56\2\uffff\6\56\4\uffff\15\56\5\uffff\3\56\1\uffff\7\56\23\uffff"+ + "\10\56\10\uffff\10\56\10\uffff\11\56\2\uffff\12\56\2\uffff\16\56\2\uffff"+ + "\1\56\30\uffff\2\56\2\uffff\11\56\2\uffff\16\56\23\uffff\22\56\36\uffff"+ + "\33\56\25\uffff\74\56\1\uffff\17\56\7\uffff\61\56\14\uffff\u0199\56\2"+ + "\uffff\u0089\56\2\uffff\33\56\57\uffff\47\56\31\uffff\13\56\25\uffff"+ + "\u01b8\56\1\uffff\145\56\2\uffff\22\56\16\uffff\2\56\137\uffff\4\56\1"+ + "\uffff\4\56\2\uffff\34\56\1\uffff\43\56\1\uffff\1\56\1\uffff\4\56\3\uffff"+ + "\1\56\1\uffff\7\56\2\uffff\7\56\16\uffff\37\56\3\uffff\30\56\1\uffff"+ + "\16\56\21\uffff\26\56\12\uffff\u0193\56\26\uffff\77\56\4\uffff\40\56"+ + "\2\uffff\u0110\56\u0372\uffff\32\56\1\uffff\131\56\14\uffff\u00d6\56"+ + "\32\uffff\14\56\5\uffff\7\56\12\uffff\2\56\10\uffff\1\56\3\uffff\40\56"+ + "\1\uffff\126\56\2\uffff\2\56\2\uffff\143\56\5\uffff\50\56\4\uffff\136"+ + "\56\1\uffff\50\56\70\uffff\57\56\1\uffff\44\56\14\uffff\56\56\1\uffff"+ + "\u0080\56\1\uffff\u1ab6\56\12\uffff\u51e6\56\132\uffff\u048d\56\3\uffff"+ + "\67\56\u0739\uffff\u2ba4\56\u215c\uffff\u012e\56\2\uffff\73\56\u0095"+ + "\uffff\7\56\14\uffff\5\56\5\uffff\32\56\1\uffff\5\56\1\uffff\1\56\1\uffff"+ + "\2\56\1\uffff\2\56\1\uffff\154\56\41\uffff\u016b\56\22\uffff\100\56\2"+ + "\uffff\66\56\50\uffff\16\56\2\uffff\20\56\20\uffff\4\56\14\uffff\5\56"+ + "\20\uffff\2\56\2\uffff\12\56\1\uffff\5\56\6\uffff\10\56\1\uffff\4\56"+ + "\4\uffff\5\56\1\uffff\u0087\56\4\uffff\7\56\2\uffff\61\56\1\uffff\1\56"+ + "\2\uffff\1\56\1\uffff\32\56\1\uffff\1\56\1\uffff\1\56\2\uffff\1\56\2"+ + "\uffff\133\56\3\uffff\6\56\2\uffff\6\56\2\uffff\6\56\2\uffff\3\56\3\uffff"+ + "\3\56\1\uffff\3\56\1\uffff\7\56", + "", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\23\62\1\121\2\62\1\120"+ + "\3\62\1\uffff\1\67\2\uffff\1\64\1\uffff\23\61\1\117\2\61\1\116\3\61\1"+ + "\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff"+ + "\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff"+ + "\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff"+ + "\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54"+ + "\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff"+ + "\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff"+ + "\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff"+ + "\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff"+ + "\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff"+ + "\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1"+ + "\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54"+ + "\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1"+ + "\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff"+ + "\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12"+ + "\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54"+ + "\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2"+ + "\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20"+ + "\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3"+ + "\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24"+ + "\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12"+ + "\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54"+ + "\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54"+ + "\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54"+ + "\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4"+ + "\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff"+ + "\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10"+ + "\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\23\62\1\121\2\62\1\120"+ + "\3\62\1\uffff\1\67\2\uffff\1\64\1\uffff\23\61\1\117\2\61\1\116\3\61\1"+ + "\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff"+ + "\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff"+ + "\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff"+ + "\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54"+ + "\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff"+ + "\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff"+ + "\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff"+ + "\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff"+ + "\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff"+ + "\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1"+ + "\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54"+ + "\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1"+ + "\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff"+ + "\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12"+ + "\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54"+ + "\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2"+ + "\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20"+ + "\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3"+ + "\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24"+ + "\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12"+ + "\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54"+ + "\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54"+ + "\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54"+ + "\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4"+ + "\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff"+ + "\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10"+ + "\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\165\123\1\122\uff8a\123", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\3\62\1\126\26\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\3\61\1\125\26\61\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\3\62\1\126\26\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\3\61\1\125\26\61\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "", + "", + "", + "", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "", + "\165\131\1\130\uff8a\131", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\132\1\uffff\1\54"+ + "\1\uffff\1\54\1\uffff\1\56\1\54\6\132\24\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\6\132\24\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32\54\1\uffff"+ + "\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4"+ + "\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff"+ + "\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff"+ + "\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54"+ + "\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff"+ + "\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff"+ + "\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff"+ + "\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff"+ + "\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff"+ + "\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1"+ + "\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54"+ + "\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1"+ + "\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff"+ + "\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12"+ + "\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54"+ + "\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2"+ + "\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20"+ + "\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3"+ + "\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24"+ + "\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12"+ + "\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54"+ + "\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54"+ + "\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54"+ + "\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4"+ + "\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff"+ + "\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10"+ + "\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "", + "\2\54\1\50\1\47\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\133\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\4\53\1\52\25\53\1\uffff"+ + "\1\51\2\uffff\1\53\1\uffff\4\53\1\52\25\53\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\50\1\47\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\110\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\53\1\uffff\1\51\2"+ + "\uffff\1\53\1\uffff\32\53\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\50\1\47\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\135\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\134\24\53\1\uffff"+ + "\1\51\2\uffff\1\53\1\uffff\6\134\24\53\1\uffff\1\54\44\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54"+ + "\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff"+ + "\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff"+ + "\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff"+ + "\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41"+ + "\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1"+ + "\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54"+ + "\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54"+ + "\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff"+ + "\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff"+ + "\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4"+ + "\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54"+ + "\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff"+ + "\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1"+ + "\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26"+ + "\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54"+ + "\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2"+ + "\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54"+ + "\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff"+ + "\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3"+ + "\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1"+ + "\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff"+ + "\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4"+ + "\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22"+ + "\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54"+ + "\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54"+ + "\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2"+ + "\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1"+ + "\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12"+ + "\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17"+ + "\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54"+ + "\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1"+ + "\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff"+ + "\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\2\54\1\50\1\47\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\110\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\53\1\uffff\1\51\2"+ + "\uffff\1\53\1\uffff\32\53\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\113\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\136\1\uffff\1\54"+ + "\1\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\1\140"+ + "\12\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67"+ + "\2\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\1\140"+ + "\12\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67"+ + "\2\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\145\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\144\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\143\24\61\1\uffff\1\54\44\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54"+ + "\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff"+ + "\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff"+ + "\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff"+ + "\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41"+ + "\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1"+ + "\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54"+ + "\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54"+ + "\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff"+ + "\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff"+ + "\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4"+ + "\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54"+ + "\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff"+ + "\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1"+ + "\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26"+ + "\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54"+ + "\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2"+ + "\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54"+ + "\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff"+ + "\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3"+ + "\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1"+ + "\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff"+ + "\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4"+ + "\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22"+ + "\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54"+ + "\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54"+ + "\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2"+ + "\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1"+ + "\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12"+ + "\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17"+ + "\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54"+ + "\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1"+ + "\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff"+ + "\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\147\1\uffff\1\54"+ + "\1\uffff\1\54\1\uffff\1\56\1\54\6\147\24\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\6\147\24\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32\54\1\uffff"+ + "\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4"+ + "\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff"+ + "\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff"+ + "\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54"+ + "\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff"+ + "\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff"+ + "\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff"+ + "\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff"+ + "\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff"+ + "\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1"+ + "\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54"+ + "\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1"+ + "\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff"+ + "\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12"+ + "\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54"+ + "\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2"+ + "\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20"+ + "\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3"+ + "\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24"+ + "\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12"+ + "\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54"+ + "\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54"+ + "\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54"+ + "\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4"+ + "\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff"+ + "\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10"+ + "\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\150\1\uffff\1\54"+ + "\1\uffff\1\54\1\uffff\1\56\1\54\6\150\24\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\6\150\24\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\50\1\47\3\54\2\uffff\1\55\1\141\1\uffff\1\151\1\37\1\140\12"+ + "\152\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\4\53\1\52\25\53\1\uffff"+ + "\1\51\2\uffff\1\53\1\uffff\4\53\1\52\25\53\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\155\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\154\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\153\24\61\1\uffff\1\54\44\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54"+ + "\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff"+ + "\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff"+ + "\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff"+ + "\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41"+ + "\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1"+ + "\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54"+ + "\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54"+ + "\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff"+ + "\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff"+ + "\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4"+ + "\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54"+ + "\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff"+ + "\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1"+ + "\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26"+ + "\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54"+ + "\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2"+ + "\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54"+ + "\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff"+ + "\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3"+ + "\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1"+ + "\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff"+ + "\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4"+ + "\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22"+ + "\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54"+ + "\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54"+ + "\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2"+ + "\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1"+ + "\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12"+ + "\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17"+ + "\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54"+ + "\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1"+ + "\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff"+ + "\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\2\54\1\50\1\47\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\157\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\156\24\53\1\uffff"+ + "\1\51\2\uffff\1\53\1\uffff\6\156\24\53\1\uffff\1\54\44\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54"+ + "\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff"+ + "\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff"+ + "\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff"+ + "\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41"+ + "\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1"+ + "\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54"+ + "\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54"+ + "\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff"+ + "\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff"+ + "\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4"+ + "\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54"+ + "\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff"+ + "\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1"+ + "\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26"+ + "\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54"+ + "\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2"+ + "\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54"+ + "\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff"+ + "\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3"+ + "\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1"+ + "\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff"+ + "\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4"+ + "\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22"+ + "\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54"+ + "\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54"+ + "\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2"+ + "\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1"+ + "\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12"+ + "\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17"+ + "\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54"+ + "\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1"+ + "\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff"+ + "\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\136\1\uffff\1\54"+ + "\1\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\4\54\1\162\3\54\1\163\4\54\1\161\5\54\1\164\5\54\1"+ + "\160\1\54\1\uffff\1\103\2\uffff\1\54\1\uffff\3\54\1\162\3\54\1\163\4"+ + "\54\1\161\5\54\1\164\5\54\1\160\1\54\1\uffff\1\54\44\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54"+ + "\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff"+ + "\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff"+ + "\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff"+ + "\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41"+ + "\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1"+ + "\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54"+ + "\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54"+ + "\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff"+ + "\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff"+ + "\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4"+ + "\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54"+ + "\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff"+ + "\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1"+ + "\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26"+ + "\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54"+ + "\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2"+ + "\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54"+ + "\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff"+ + "\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3"+ + "\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1"+ + "\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff"+ + "\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4"+ + "\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22"+ + "\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54"+ + "\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54"+ + "\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2"+ + "\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1"+ + "\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12"+ + "\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17"+ + "\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54"+ + "\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1"+ + "\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff"+ + "\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\165\1\uffff\1\54"+ + "\1\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\170\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\167\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\166\24\61\1\uffff\1\54\44\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54"+ + "\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff"+ + "\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff"+ + "\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff"+ + "\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41"+ + "\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1"+ + "\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54"+ + "\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54"+ + "\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff"+ + "\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff"+ + "\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4"+ + "\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54"+ + "\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff"+ + "\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1"+ + "\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26"+ + "\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54"+ + "\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2"+ + "\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54"+ + "\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff"+ + "\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3"+ + "\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1"+ + "\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff"+ + "\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4"+ + "\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22"+ + "\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54"+ + "\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54"+ + "\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2"+ + "\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1"+ + "\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12"+ + "\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17"+ + "\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54"+ + "\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1"+ + "\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff"+ + "\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\170\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\167\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\166\24\61\1\uffff\1\54\44\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54"+ + "\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff"+ + "\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff"+ + "\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff"+ + "\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41"+ + "\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1"+ + "\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54"+ + "\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54"+ + "\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff"+ + "\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff"+ + "\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4"+ + "\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54"+ + "\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff"+ + "\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1"+ + "\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26"+ + "\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54"+ + "\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2"+ + "\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54"+ + "\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff"+ + "\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3"+ + "\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1"+ + "\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff"+ + "\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4"+ + "\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22"+ + "\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54"+ + "\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54"+ + "\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2"+ + "\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1"+ + "\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12"+ + "\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17"+ + "\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54"+ + "\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1"+ + "\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff"+ + "\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\170\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\167\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\166\24\61\1\uffff\1\54\44\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54"+ + "\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff"+ + "\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff"+ + "\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff"+ + "\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41"+ + "\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1"+ + "\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54"+ + "\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54"+ + "\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff"+ + "\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff"+ + "\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4"+ + "\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54"+ + "\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff"+ + "\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1"+ + "\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26"+ + "\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54"+ + "\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2"+ + "\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54"+ + "\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff"+ + "\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3"+ + "\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1"+ + "\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff"+ + "\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4"+ + "\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22"+ + "\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54"+ + "\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54"+ + "\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2"+ + "\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1"+ + "\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12"+ + "\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17"+ + "\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54"+ + "\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1"+ + "\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff"+ + "\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\171\1\uffff\1\54"+ + "\1\uffff\1\54\1\uffff\1\56\1\54\6\171\24\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\6\171\24\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\172\1\uffff\1\54"+ + "\1\uffff\1\54\1\uffff\1\56\1\54\6\172\24\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\6\172\24\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\173\1\uffff\1\54"+ + "\1\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\50\1\47\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\152\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\4\53\1\52\25\53\1\uffff"+ + "\1\51\2\uffff\1\53\1\uffff\4\53\1\52\25\53\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\176\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\175\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\174\24\61\1\uffff\1\54\44\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54"+ + "\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff"+ + "\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff"+ + "\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff"+ + "\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41"+ + "\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1"+ + "\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54"+ + "\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54"+ + "\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff"+ + "\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff"+ + "\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4"+ + "\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54"+ + "\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff"+ + "\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1"+ + "\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26"+ + "\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54"+ + "\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2"+ + "\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54"+ + "\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff"+ + "\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3"+ + "\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1"+ + "\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff"+ + "\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4"+ + "\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22"+ + "\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54"+ + "\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54"+ + "\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2"+ + "\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1"+ + "\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12"+ + "\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17"+ + "\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54"+ + "\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1"+ + "\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff"+ + "\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\176\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\175\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\174\24\61\1\uffff\1\54\44\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54"+ + "\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff"+ + "\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff"+ + "\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff"+ + "\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41"+ + "\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1"+ + "\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54"+ + "\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54"+ + "\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff"+ + "\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff"+ + "\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4"+ + "\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54"+ + "\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff"+ + "\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1"+ + "\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26"+ + "\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54"+ + "\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2"+ + "\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54"+ + "\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff"+ + "\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3"+ + "\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1"+ + "\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff"+ + "\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4"+ + "\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22"+ + "\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54"+ + "\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54"+ + "\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2"+ + "\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1"+ + "\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12"+ + "\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17"+ + "\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54"+ + "\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1"+ + "\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff"+ + "\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\176\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\175\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\174\24\61\1\uffff\1\54\44\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54"+ + "\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff"+ + "\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff"+ + "\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff"+ + "\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41"+ + "\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1"+ + "\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54"+ + "\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54"+ + "\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff"+ + "\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff"+ + "\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4"+ + "\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54"+ + "\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff"+ + "\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1"+ + "\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26"+ + "\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54"+ + "\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2"+ + "\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54"+ + "\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff"+ + "\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3"+ + "\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1"+ + "\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff"+ + "\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4"+ + "\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22"+ + "\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54"+ + "\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54"+ + "\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2"+ + "\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1"+ + "\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12"+ + "\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17"+ + "\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54"+ + "\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1"+ + "\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff"+ + "\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\176\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\175\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\174\24\61\1\uffff\1\54\44\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54"+ + "\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff"+ + "\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff"+ + "\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff"+ + "\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41"+ + "\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1"+ + "\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54"+ + "\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54"+ + "\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff"+ + "\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff"+ + "\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4"+ + "\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54"+ + "\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff"+ + "\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1"+ + "\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26"+ + "\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54"+ + "\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2"+ + "\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54"+ + "\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff"+ + "\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3"+ + "\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1"+ + "\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff"+ + "\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4"+ + "\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22"+ + "\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54"+ + "\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54"+ + "\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2"+ + "\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1"+ + "\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12"+ + "\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17"+ + "\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54"+ + "\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1"+ + "\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff"+ + "\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\2\54\1\50\1\47\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u0080\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\177\24\53\1\uffff"+ + "\1\51\2\uffff\1\53\1\uffff\6\177\24\53\1\uffff\1\54\44\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54"+ + "\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff"+ + "\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff"+ + "\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff"+ + "\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41"+ + "\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1"+ + "\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54"+ + "\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54"+ + "\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff"+ + "\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff"+ + "\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4"+ + "\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54"+ + "\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff"+ + "\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1"+ + "\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26"+ + "\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54"+ + "\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2"+ + "\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54"+ + "\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff"+ + "\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3"+ + "\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1"+ + "\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff"+ + "\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4"+ + "\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22"+ + "\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54"+ + "\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54"+ + "\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2"+ + "\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1"+ + "\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12"+ + "\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17"+ + "\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54"+ + "\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1"+ + "\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff"+ + "\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\5\54\1\u0081\25\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\4\54\1\u0081\25\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\11\54\1\u0083\5\54\1\u0082\13\54\1\uffff\1\103\2\uffff"+ + "\1\54\1\uffff\10\54\1\u0083\5\54\1\u0082\13\54\1\uffff\1\54\44\uffff"+ + "\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54"+ + "\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff"+ + "\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff"+ + "\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54"+ + "\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff"+ + "\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff"+ + "\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\1\54\1\u0084\31\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\1\u0084\31\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31"+ + "\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130"+ + "\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54"+ + "\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107"+ + "\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12"+ + "\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1"+ + "\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\17\54\1\u0085\13\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\16\54\1\u0085\13\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\5\54\1\u0086\25\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\4\54\1\u0086\25\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\165\1\uffff\1\54"+ + "\1\uffff\1\54\1\uffff\1\56\4\54\1\u0089\3\54\1\u008a\4\54\1\u0088\5\54"+ + "\1\u008b\5\54\1\u0087\1\54\1\uffff\1\103\2\uffff\1\54\1\uffff\3\54\1"+ + "\u0089\3\54\1\u008a\4\54\1\u0088\5\54\1\u008b\5\54\1\u0087\1\54\1\uffff"+ + "\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4"+ + "\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff"+ + "\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff"+ + "\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54"+ + "\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff"+ + "\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff"+ + "\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff"+ + "\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff"+ + "\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff"+ + "\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1"+ + "\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54"+ + "\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1"+ + "\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff"+ + "\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12"+ + "\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54"+ + "\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2"+ + "\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20"+ + "\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3"+ + "\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24"+ + "\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12"+ + "\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54"+ + "\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54"+ + "\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54"+ + "\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4"+ + "\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff"+ + "\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10"+ + "\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u008e\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u008d\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u008c\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u008e\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u008d\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u008c\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u008e\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u008d\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u008c\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\u008f\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u008f\24\54\1\uffff\1\103\2\uffff"+ + "\1\54\1\uffff\6\u008f\24\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\u0090\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u0090\24\54\1\uffff\1\103\2\uffff"+ + "\1\54\1\uffff\6\u0090\24\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\u0091\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\1\56\4\54\1\u0089\3\54\1\u008a\4\54\1\u0088"+ + "\5\54\1\u008b\5\54\1\u0087\1\54\1\uffff\1\103\2\uffff\1\54\1\uffff\3"+ + "\54\1\u0089\3\54\1\u008a\4\54\1\u0088\5\54\1\u008b\5\54\1\u0087\1\54"+ + "\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1"+ + "\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54"+ + "\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23"+ + "\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54"+ + "\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u0094\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u0093\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u0092\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u0094\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u0093\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u0092\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u0094\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u0093\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u0092\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u0094\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u0093\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u0092\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\50\1\47\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u0096\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u0095\24\53\1\uffff"+ + "\1\51\2\uffff\1\53\1\uffff\6\u0095\24\53\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\1\54\1\u0097\31\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\1\u0097\31\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31"+ + "\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130"+ + "\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54"+ + "\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107"+ + "\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12"+ + "\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1"+ + "\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\16\54\1\u0098\14\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\15\54\1\u0098\14\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\14\54\1\u009a\1\54\1\u0099\14\54\1\uffff\1\103\2\uffff"+ + "\1\54\1\uffff\13\54\1\u009a\1\54\1\u0099\14\54\1\uffff\1\54\44\uffff"+ + "\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54"+ + "\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff"+ + "\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff"+ + "\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54"+ + "\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff"+ + "\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff"+ + "\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\24\54\1\u009c\4\54\1\u009b\1\54\1\uffff\1\103\2\uffff"+ + "\1\54\1\uffff\23\54\1\u009c\4\54\1\u009b\1\54\1\uffff\1\54\44\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54"+ + "\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff"+ + "\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff"+ + "\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54"+ + "\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff"+ + "\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff"+ + "\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\25\54\1\u009d\5\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\24\54\1\u009d\5\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\3\54\1\u009e\27\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\2\54\1\u009e\27\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\5\54\1\u009f\25\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\4\54\1\u009f\25\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\11\54\1\u00a1\5\54\1\u00a0\13\54\1\uffff\1\103\2\uffff"+ + "\1\54\1\uffff\10\54\1\u00a1\5\54\1\u00a0\13\54\1\uffff\1\54\44\uffff"+ + "\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54"+ + "\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff"+ + "\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff"+ + "\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54"+ + "\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff"+ + "\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff"+ + "\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\1\54\1\u00a2\31\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\1\u00a2\31\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31"+ + "\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130"+ + "\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54"+ + "\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107"+ + "\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12"+ + "\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1"+ + "\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\17\54\1\u00a3\13\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\16\54\1\u00a3\13\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\5\54\1\u00a4\25\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\4\54\1\u00a4\25\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00a7\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00a6\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00a5\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00a7\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00a6\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00a5\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00a7\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00a6\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00a5\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\u00a8\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00a8\24\54\1\uffff\1\103\2\uffff"+ + "\1\54\1\uffff\6\u00a8\24\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32\54\1\uffff"+ + "\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4"+ + "\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff"+ + "\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff"+ + "\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54"+ + "\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff"+ + "\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff"+ + "\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff"+ + "\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff"+ + "\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff"+ + "\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1"+ + "\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54"+ + "\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1"+ + "\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff"+ + "\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12"+ + "\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54"+ + "\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2"+ + "\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20"+ + "\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3"+ + "\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24"+ + "\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12"+ + "\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54"+ + "\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54"+ + "\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54"+ + "\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4"+ + "\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff"+ + "\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10"+ + "\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\u00a9\1\uffff\1\140\12\165\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\56\4\54\1\u0089\3\54\1\u008a\4\54\1\u0088"+ + "\5\54\1\u008b\5\54\1\u0087\1\54\1\uffff\1\103\2\uffff\1\54\1\uffff\3"+ + "\54\1\u0089\3\54\1\u008a\4\54\1\u0088\5\54\1\u008b\5\54\1\u0087\1\54"+ + "\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1"+ + "\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54"+ + "\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23"+ + "\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54"+ + "\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00ab\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\u00af\1\uffff"+ + "\1\u00ae\2\uffff\1\u00b0\1\uffff\32\u00aa\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00ab\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\u00af\1\uffff"+ + "\1\u00ae\2\uffff\1\u00b0\1\uffff\32\u00aa\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00ab\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\u00af\1\uffff"+ + "\1\u00ae\2\uffff\1\u00b0\1\uffff\32\u00aa\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00ab\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\u00af\1\uffff"+ + "\1\u00ae\2\uffff\1\u00b0\1\uffff\32\u00aa\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\50\1\47\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\110\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\53\1\uffff\1\51\2"+ + "\uffff\1\53\1\uffff\32\53\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\22\54\1\u00b1\10\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\21\54\1\u00b1\10\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\24\54\1\u00b2\6\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\23\54\1\u00b2\6\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\25\54\1\u00b3\5\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\24\54\1\u00b3\5\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\14\54\1\u00b4\16\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\13\54\1\u00b4\16\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u00b5\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u00b5\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\5\54\1\u00b6\25\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\4\54\1\u00b6\25\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\22\54\1\u00b7\10\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\21\54\1\u00b7\10\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\17\54\1\u00b8\13\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\16\54\1\u00b8\13\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\1\54\1\u00b9\31\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\1\u00b9\31\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31"+ + "\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130"+ + "\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54"+ + "\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107"+ + "\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12"+ + "\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1"+ + "\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\16\54\1\u00ba\14\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\15\54\1\u00ba\14\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\14\54\1\u00bc\1\54\1\u00bb\14\54\1\uffff\1\103\2\uffff"+ + "\1\54\1\uffff\13\54\1\u00bc\1\54\1\u00bb\14\54\1\uffff\1\54\44\uffff"+ + "\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54"+ + "\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff"+ + "\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff"+ + "\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54"+ + "\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff"+ + "\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff"+ + "\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\24\54\1\u00be\4\54\1\u00bd\1\54\1\uffff\1\103\2\uffff"+ + "\1\54\1\uffff\23\54\1\u00be\4\54\1\u00bd\1\54\1\uffff\1\54\44\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54"+ + "\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff"+ + "\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff"+ + "\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54"+ + "\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff"+ + "\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff"+ + "\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\25\54\1\u00bf\5\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\24\54\1\u00bf\5\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\3\54\1\u00c0\27\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\2\54\1\u00c0\27\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32\54\1\uffff"+ + "\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4"+ + "\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff"+ + "\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff"+ + "\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54"+ + "\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff"+ + "\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff"+ + "\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff"+ + "\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff"+ + "\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff"+ + "\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1"+ + "\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54"+ + "\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1"+ + "\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff"+ + "\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12"+ + "\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54"+ + "\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2"+ + "\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20"+ + "\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3"+ + "\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24"+ + "\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12"+ + "\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54"+ + "\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54"+ + "\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54"+ + "\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4"+ + "\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff"+ + "\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10"+ + "\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\u00c1\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\32\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff"+ + "\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00ab\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\u00af\1\uffff"+ + "\1\u00ae\2\uffff\1\u00b0\1\uffff\32\u00aa\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00ab\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\u00af\1\uffff"+ + "\1\u00ae\2\uffff\1\u00b0\1\uffff\32\u00aa\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00ab\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\u00af\1\uffff"+ + "\1\u00ae\2\uffff\1\u00b0\1\uffff\32\u00aa\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\165\u00c3\1\u00c2\uff8a\u00c3", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\63\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\62\1\uffff\1\67\2"+ + "\uffff\1\64\1\uffff\32\61\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u00c4\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u00c4\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\10\54\1\u00c5\22\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\7\54\1\u00c5\22\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\24\54\1\u00c6\6\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\23\54\1\u00c6\6\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\11\54\1\u00c7\21\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\10\54\1\u00c7\21\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u00c8\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u00c8\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\16\54\1\u00c9\14\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\15\54\1\u00c9\14\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\22\54\1\u00ca\10\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\21\54\1\u00ca\10\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\24\54\1\u00cb\6\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\23\54\1\u00cb\6\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\25\54\1\u00cc\5\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\24\54\1\u00cc\5\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\14\54\1\u00cd\16\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\13\54\1\u00cd\16\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u00ce\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u00ce\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\5\54\1\u00cf\25\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\4\54\1\u00cf\25\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\22\54\1\u00d0\10\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\21\54\1\u00d0\10\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\17\54\1\u00d1\13\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\16\54\1\u00d1\13\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\u00d2\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\1\56\4\54\1\u0089\3\54\1\u008a\4\54\1\u0088"+ + "\5\54\1\u008b\5\54\1\u0087\1\54\1\uffff\1\103\2\uffff\1\54\1\uffff\3"+ + "\54\1\u0089\3\54\1\u008a\4\54\1\u0088\5\54\1\u008b\5\54\1\u0087\1\54"+ + "\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1"+ + "\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54"+ + "\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23"+ + "\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54"+ + "\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00d4\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00d5\24\u00af"+ + "\1\uffff\1\u00ae\2\uffff\1\u00b0\1\uffff\6\u00d3\24\u00aa\1\uffff\1\54"+ + "\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1"+ + "\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14"+ + "\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff"+ + "\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54"+ + "\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff"+ + "\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff"+ + "\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff"+ + "\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff"+ + "\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff"+ + "\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1"+ + "\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54"+ + "\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1"+ + "\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff"+ + "\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12"+ + "\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54"+ + "\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2"+ + "\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20"+ + "\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3"+ + "\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24"+ + "\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12"+ + "\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54"+ + "\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54"+ + "\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54"+ + "\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4"+ + "\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff"+ + "\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10"+ + "\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00ab\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\u00af\1\uffff"+ + "\1\u00ae\2\uffff\1\u00b0\1\uffff\32\u00aa\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u00d6\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u00d6\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\5\54\1\u00d7\25\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\4\54\1\u00d7\25\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u00d8\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u00d8\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\4\54\1\u00d9\26\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\3\54\1\u00d9\26\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u00da\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u00da\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\10\54\1\u00db\22\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\7\54\1\u00db\22\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\24\54\1\u00dc\6\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\23\54\1\u00dc\6\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\11\54\1\u00dd\21\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\10\54\1\u00dd\21\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u00de\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u00de\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\16\54\1\u00df\14\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\15\54\1\u00df\14\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\1\140\12\165\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\56\4\54\1\u0089\3\54\1\u008a\4\54\1\u0088"+ + "\5\54\1\u008b\1\u00e0\4\54\1\u0087\1\54\1\uffff\1\103\2\uffff\1\54\1"+ + "\uffff\3\54\1\u0089\3\54\1\u008a\4\54\1\u0088\5\54\1\u008b\5\54\1\u0087"+ + "\1\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff"+ + "\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00e3\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00e2\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00e1\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00e5\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00e6\24\u00af"+ + "\1\uffff\1\u00ae\2\uffff\1\u00b0\1\uffff\6\u00e4\24\u00aa\1\uffff\1\54"+ + "\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1"+ + "\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14"+ + "\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff"+ + "\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54"+ + "\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff"+ + "\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff"+ + "\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff"+ + "\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff"+ + "\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff"+ + "\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1"+ + "\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54"+ + "\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1"+ + "\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff"+ + "\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12"+ + "\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54"+ + "\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2"+ + "\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20"+ + "\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3"+ + "\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24"+ + "\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12"+ + "\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54"+ + "\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54"+ + "\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54"+ + "\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4"+ + "\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff"+ + "\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10"+ + "\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00e3\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00e2\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00e1\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u00e7\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u00e7\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\5\54\1\u00e8\25\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\4\54\1\u00e8\25\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u00e9\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u00e9\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u00ea\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u00ea\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\5\54\1\u00eb\25\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\4\54\1\u00eb\25\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u00ec\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u00ec\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\4\54\1\u00ed\26\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\3\54\1\u00ed\26\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\1\140\12\u00ee\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\32\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff"+ + "\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00f1\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00f0\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00ef\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00f1\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00f0\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00ef\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00f1\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00f0\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00ef\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00f1\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00f0\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00ef\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00f3\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00f4\24\u00af"+ + "\1\uffff\1\u00ae\2\uffff\1\u00b0\1\uffff\6\u00f2\24\u00aa\1\uffff\1\54"+ + "\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1"+ + "\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14"+ + "\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff"+ + "\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54"+ + "\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff"+ + "\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff"+ + "\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff"+ + "\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff"+ + "\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff"+ + "\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1"+ + "\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54"+ + "\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1"+ + "\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff"+ + "\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12"+ + "\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54"+ + "\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2"+ + "\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20"+ + "\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3"+ + "\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24"+ + "\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12"+ + "\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54"+ + "\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54"+ + "\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54"+ + "\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4"+ + "\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff"+ + "\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10"+ + "\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00f1\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00f0\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00ef\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\3\54\1\u00f5\27\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\2\54\1\u00f5\27\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u00f6\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u00f6\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\5\54\1\u00f7\25\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\4\54\1\u00f7\25\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u00f8\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u00f8\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12\u00f9\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\32\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff"+ + "\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00fc\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00fb\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00fa\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00fc\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00fb\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00fa\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00fc\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00fb\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00fa\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00fc\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00fb\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00fa\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00fe\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00ff\24\u00af"+ + "\1\uffff\1\u00ae\2\uffff\1\u00b0\1\uffff\6\u00fd\24\u00aa\1\uffff\1\54"+ + "\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1"+ + "\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14"+ + "\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff"+ + "\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54"+ + "\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff"+ + "\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff"+ + "\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff"+ + "\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff"+ + "\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff"+ + "\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20"+ + "\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff"+ + "\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1"+ + "\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54"+ + "\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1"+ + "\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff"+ + "\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12"+ + "\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54"+ + "\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2"+ + "\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20"+ + "\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3"+ + "\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24"+ + "\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12"+ + "\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54"+ + "\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54"+ + "\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54"+ + "\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22"+ + "\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4"+ + "\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff"+ + "\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10"+ + "\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\66\1\65\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1\54\12"+ + "\u00fc\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\6\u00fb\24\62\1\uffff"+ + "\1\67\2\uffff\1\64\1\uffff\6\u00fa\24\61\1\uffff\1\54\44\uffff\7\54\1"+ + "\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\17\54\1\u0100\13\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\16\54\1\u0100\13\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\3\54\1\u0101\27\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\2\54\1\u0101\27\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\1\140\12\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\32\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff"+ + "\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00ab\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\u00af\1\uffff"+ + "\1\u00ae\2\uffff\1\u00b0\1\uffff\32\u00aa\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00ab\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\u00af\1\uffff"+ + "\1\u00ae\2\uffff\1\u00b0\1\uffff\32\u00aa\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00ab\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\u00af\1\uffff"+ + "\1\u00ae\2\uffff\1\u00b0\1\uffff\32\u00aa\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00ab\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\u00af\1\uffff"+ + "\1\u00ae\2\uffff\1\u00b0\1\uffff\32\u00aa\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00ab\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\u00af\1\uffff"+ + "\1\u00ae\2\uffff\1\u00b0\1\uffff\32\u00aa\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\2\54\1\u00ad\1\u00ac\3\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\1"+ + "\54\12\u00ab\1\uffff\1\54\1\uffff\1\54\1\uffff\1\56\1\54\32\u00af\1\uffff"+ + "\1\u00ae\2\uffff\1\u00b0\1\uffff\32\u00aa\1\uffff\1\54\44\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff"+ + "\2\54\1\uffff\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11"+ + "\uffff\1\54\21\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54"+ + "\7\uffff\5\54\1\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54"+ + "\4\uffff\u0087\54\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20"+ + "\54\41\uffff\46\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21"+ + "\54\1\uffff\27\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff"+ + "\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff"+ + "\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f"+ + "\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1"+ + "\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff"+ + "\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2"+ + "\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff"+ + "\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff"+ + "\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3"+ + "\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54"+ + "\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10"+ + "\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff"+ + "\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54"+ + "\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3"+ + "\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1"+ + "\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4"+ + "\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff"+ + "\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff"+ + "\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2"+ + "\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10"+ + "\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54"+ + "\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54"+ + "\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54"+ + "\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14"+ + "\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1"+ + "\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5"+ + "\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72"+ + "\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44"+ + "\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2"+ + "\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff"+ + "\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff"+ + "\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1"+ + "\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54"+ + "\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125"+ + "\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1"+ + "\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54"+ + "\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54"+ + "\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff"+ + "\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff"+ + "\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff"+ + "\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff"+ + "\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65"+ + "\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54"+ + "\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54"+ + "\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1"+ + "\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\16\54\1\u0102\14\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\15\54\1\u0102\14\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\17\54\1\u0103\13\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\16\54\1\u0103\13\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\4\54\1\u0104\26\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\3\54\1\u0104\26\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\16\54\1\u0105\14\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\15\54\1\u0105\14\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u0106\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u0106\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\54\1\uffff\1\54\1\uffff\13\54\1\uffff\1\54\1\uffff"+ + "\1\54\1\uffff\1\56\4\54\1\u0107\26\54\1\uffff\1\103\2\uffff\1\54\1\uffff"+ + "\3\54\1\u0107\26\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b"+ + "\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff"+ + "\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff"+ + "\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff"+ + "\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff"+ + "\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff"+ + "\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff"+ + "\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff"+ + "\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2"+ + "\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2"+ + "\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff"+ + "\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25"+ + "\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54"+ + "\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff"+ + "\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff"+ + "\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2"+ + "\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54"+ + "\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54"+ + "\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2"+ + "\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff"+ + "\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4"+ + "\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54"+ + "\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11"+ + "\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1"+ + "\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff"+ + "\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff"+ + "\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2"+ + "\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27"+ + "\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54"+ + "\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54"+ + "\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1"+ + "\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54"+ + "\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6"+ + "\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff"+ + "\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6"+ + "\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42"+ + "\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1"+ + "\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54"+ + "\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132"+ + "\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff"+ + "\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff"+ + "\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47"+ + "\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff\u0276\54\12"+ + "\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54"+ + "\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64"+ + "\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12"+ + "\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff"+ + "\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff\40\54\u0300"+ + "\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff\26\54\2\uffff"+ + "\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1"+ + "\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54"+ + "\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5"+ + "\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54\10\uffff\11\54"+ + "\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54\2\uffff\11\54"+ + "\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74\54\1\uffff\17"+ + "\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2\uffff\33\54\57"+ + "\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff\145\54\2\uffff"+ + "\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff\34\54\1\uffff"+ + "\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7\54\2\uffff\7"+ + "\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff\26\54\12\uffff"+ + "\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54\u0372\uffff\32"+ + "\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5\uffff\7\54\12\uffff"+ + "\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54\2\uffff\2\54\2\uffff"+ + "\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50\54\70\uffff\57\54\1\uffff"+ + "\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6"+ + "\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff\u2ba4\54\u215c\uffff"+ + "\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff\5\54\5\uffff\32\54"+ + "\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2\54\1\uffff\154\54\41"+ + "\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50\uffff\16\54\2\uffff"+ + "\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54\2\uffff\12\54\1\uffff"+ + "\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1\uffff\u0087\54\4\uffff"+ + "\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54\1\uffff\32\54\1\uffff\1"+ + "\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54\3\uffff\6\54\2\uffff\6\54"+ + "\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\23\54\1\u0108\7\54\1\uffff\1\103\2\uffff\1\54"+ + "\1\uffff\22\54\1\u0108\7\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\1\54\1\uffff\1\54\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff"+ + "\u017b\54\31\uffff\162\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21"+ + "\uffff\130\54\5\uffff\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1"+ + "\uffff\1\54\1\uffff\24\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54"+ + "\1\uffff\107\54\1\uffff\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46"+ + "\54\2\uffff\7\54\1\uffff\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27"+ + "\54\1\uffff\12\54\13\uffff\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff"+ + "\1\54\3\uffff\1\54\1\uffff\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff"+ + "\60\54\2\uffff\73\54\2\uffff\3\54\60\uffff\62\54\u014f\uffff\71\54\2"+ + "\uffff\22\54\2\uffff\5\54\3\uffff\31\54\20\uffff\3\54\1\uffff\10\54\2"+ + "\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff"+ + "\11\54\2\uffff\2\54\2\uffff\3\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\25\54\6\uffff\3\54\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54"+ + "\1\uffff\7\54\1\uffff\2\54\1\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff"+ + "\5\54\4\uffff\2\54\2\uffff\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17"+ + "\54\14\uffff\3\54\1\uffff\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7"+ + "\54\1\uffff\2\54\1\uffff\5\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54"+ + "\2\uffff\1\54\17\uffff\4\54\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54"+ + "\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\5\54\2\uffff\10\54\3\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff"+ + "\2\54\1\uffff\3\54\4\uffff\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3"+ + "\54\1\uffff\4\54\3\uffff\2\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54"+ + "\3\uffff\3\54\3\uffff\10\54\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1"+ + "\uffff\4\54\11\uffff\1\54\17\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1"+ + "\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff"+ + "\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff"+ + "\5\54\2\uffff\11\54\1\uffff\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1"+ + "\54\1\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3"+ + "\54\1\uffff\27\54\1\uffff\20\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54"+ + "\11\uffff\1\54\10\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54"+ + "\3\uffff\30\54\1\uffff\11\54\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4"+ + "\uffff\6\54\1\uffff\1\54\1\uffff\10\54\22\uffff\3\54\14\uffff\72\54\4"+ + "\uffff\35\54\45\uffff\2\54\1\uffff\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff"+ + "\1\54\6\uffff\4\54\1\uffff\7\54\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54"+ + "\2\uffff\2\54\1\uffff\15\54\1\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1"+ + "\uffff\6\54\2\uffff\12\54\2\uffff\2\54\42\uffff\72\54\4\uffff\12\54\1"+ + "\uffff\42\54\6\uffff\33\54\4\uffff\10\54\1\uffff\44\54\1\uffff\17\54"+ + "\2\uffff\1\54\60\uffff\42\54\1\uffff\5\54\1\uffff\2\54\1\uffff\7\54\3"+ + "\uffff\4\54\6\uffff\32\54\106\uffff\46\54\12\uffff\51\54\2\uffff\1\54"+ + "\4\uffff\132\54\5\uffff\104\54\5\uffff\122\54\6\uffff\7\54\1\uffff\77"+ + "\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54"+ + "\2\uffff\47\54\1\uffff\1\54\1\uffff\4\54\2\uffff\37\54\1\uffff\1\54\1"+ + "\uffff\4\54\2\uffff\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff"+ + "\7\54\1\uffff\27\54\1\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7"+ + "\54\1\uffff\47\54\1\uffff\23\54\6\uffff\34\54\43\uffff\125\54\14\uffff"+ + "\u0276\54\12\uffff\32\54\5\uffff\121\54\17\uffff\15\54\1\uffff\7\54\13"+ + "\uffff\27\54\11\uffff\24\54\14\uffff\15\54\1\uffff\3\54\1\uffff\2\54"+ + "\14\uffff\64\54\2\uffff\50\54\2\uffff\12\54\6\uffff\12\54\6\uffff\16"+ + "\54\2\uffff\12\54\6\uffff\130\54\10\uffff\52\54\126\uffff\35\54\3\uffff"+ + "\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff\52\54\2\uffff\5\54\153\uffff"+ + "\40\54\u0300\uffff\154\54\u0094\uffff\u009c\54\4\uffff\132\54\6\uffff"+ + "\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6\54\2\uffff\10\54\1\uffff"+ + "\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54\2\uffff\65\54\1\uffff\7"+ + "\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3\uffff\4\54\2\uffff\6\54"+ + "\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff\10\54\10\uffff\10\54"+ + "\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff\1\54\30\uffff\2\54"+ + "\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff\33\54\25\uffff\74"+ + "\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2\uffff\u0089\54\2"+ + "\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff\u01b8\54\1\uffff"+ + "\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1\uffff\4\54\2\uffff"+ + "\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff\1\54\1\uffff\7"+ + "\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff\16\54\21\uffff"+ + "\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54\2\uffff\u0110\54"+ + "\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54\32\uffff\14\54\5"+ + "\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54\1\uffff\126\54"+ + "\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136\54\1\uffff\50"+ + "\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff\u0080\54\1\uffff"+ + "\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff\67\54\u0739\uffff"+ + "\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095\uffff\7\54\14\uffff"+ + "\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff\2\54\1\uffff\2"+ + "\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2\uffff\66\54\50"+ + "\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54\20\uffff\2\54"+ + "\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54\4\uffff\5\54\1"+ + "\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54\2\uffff\1\54"+ + "\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2\uffff\133\54"+ + "\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff\3\54\1\uffff"+ + "\3\54\1\uffff\7\54", + "\7\54\2\uffff\1\55\1\141\1\uffff\1\141\1\uffff\13\54\1\uffff\1\54\1"+ + "\uffff\1\54\1\uffff\1\56\33\54\1\uffff\1\103\2\uffff\1\54\1\uffff\32"+ + "\54\1\uffff\1\54\44\uffff\7\54\1\uffff\2\54\1\uffff\1\54\1\uffff\1\54"+ + "\1\uffff\4\54\1\uffff\3\54\1\uffff\2\54\1\uffff\u017b\54\31\uffff\162"+ + "\54\4\uffff\14\54\16\uffff\5\54\11\uffff\1\54\21\uffff\130\54\5\uffff"+ + "\23\54\12\uffff\1\54\3\uffff\1\54\7\uffff\5\54\1\uffff\1\54\1\uffff\24"+ + "\54\1\uffff\54\54\1\uffff\54\54\4\uffff\u0087\54\1\uffff\107\54\1\uffff"+ + "\46\54\2\uffff\2\54\6\uffff\20\54\41\uffff\46\54\2\uffff\7\54\1\uffff"+ + "\47\54\1\uffff\2\54\6\uffff\21\54\1\uffff\27\54\1\uffff\12\54\13\uffff"+ + "\33\54\5\uffff\5\54\27\uffff\12\54\5\uffff\1\54\3\uffff\1\54\1\uffff"+ + "\32\54\5\uffff\31\54\7\uffff\175\54\1\uffff\60\54\2\uffff\73\54\2\uffff"+ + "\3\54\60\uffff\62\54\u014f\uffff\71\54\2\uffff\22\54\2\uffff\5\54\3\uffff"+ + "\31\54\20\uffff\3\54\1\uffff\10\54\2\uffff\2\54\2\uffff\26\54\1\uffff"+ + "\7\54\1\uffff\1\54\3\uffff\4\54\2\uffff\11\54\2\uffff\2\54\2\uffff\3"+ + "\54\11\uffff\1\54\4\uffff\2\54\1\uffff\5\54\2\uffff\25\54\6\uffff\3\54"+ + "\1\uffff\6\54\4\uffff\2\54\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1"+ + "\uffff\2\54\1\uffff\2\54\2\uffff\1\54\1\uffff\5\54\4\uffff\2\54\2\uffff"+ + "\3\54\13\uffff\4\54\1\uffff\1\54\7\uffff\17\54\14\uffff\3\54\1\uffff"+ + "\11\54\1\uffff\3\54\1\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5"+ + "\54\2\uffff\12\54\1\uffff\3\54\1\uffff\3\54\2\uffff\1\54\17\uffff\4\54"+ + "\2\uffff\12\54\1\uffff\1\54\17\uffff\3\54\1\uffff\10\54\2\uffff\2\54"+ + "\2\uffff\26\54\1\uffff\7\54\1\uffff\2\54\1\uffff\5\54\2\uffff\10\54\3"+ + "\uffff\2\54\2\uffff\3\54\10\uffff\2\54\4\uffff\2\54\1\uffff\3\54\4\uffff"+ + "\14\54\20\uffff\2\54\1\uffff\6\54\3\uffff\3\54\1\uffff\4\54\3\uffff\2"+ + "\54\1\uffff\1\54\1\uffff\2\54\3\uffff\2\54\3\uffff\3\54\3\uffff\10\54"+ + "\1\uffff\3\54\4\uffff\5\54\3\uffff\3\54\1\uffff\4\54\11\uffff\1\54\17"+ + "\uffff\24\54\6\uffff\3\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1"+ + "\uffff\12\54\1\uffff\5\54\4\uffff\7\54\1\uffff\3\54\1\uffff\4\54\7\uffff"+ + "\2\54\11\uffff\2\54\4\uffff\12\54\22\uffff\2\54\1\uffff\10\54\1\uffff"+ + "\3\54\1\uffff\27\54\1\uffff\12\54\1\uffff\5\54\2\uffff\11\54\1\uffff"+ + "\3\54\1\uffff\4\54\7\uffff\2\54\7\uffff\1\54\1\uffff\2\54\4\uffff\12"+ + "\54\22\uffff\2\54\1\uffff\10\54\1\uffff\3\54\1\uffff\27\54\1\uffff\20"+ + "\54\4\uffff\6\54\2\uffff\3\54\1\uffff\4\54\11\uffff\1\54\10\uffff\2\54"+ + "\4\uffff\12\54\22\uffff\2\54\1\uffff\22\54\3\uffff\30\54\1\uffff\11\54"+ + "\1\uffff\1\54\2\uffff\7\54\3\uffff\1\54\4\uffff\6\54\1\uffff\1\54\1\uffff"+ + "\10\54\22\uffff\3\54\14\uffff\72\54\4\uffff\35\54\45\uffff\2\54\1\uffff"+ + "\1\54\2\uffff\2\54\1\uffff\1\54\2\uffff\1\54\6\uffff\4\54\1\uffff\7\54"+ + "\1\uffff\3\54\1\uffff\1\54\1\uffff\1\54\2\uffff\2\54\1\uffff\15\54\1"+ + "\uffff\3\54\2\uffff\5\54\1\uffff\1\54\1\uffff\6\54\2\uffff\12\54\2\uffff"+ + "\2\54\42\uffff\72\54\4\uffff\12\54\1\uffff\42\54\6\uffff\33\54\4\uffff"+ + "\10\54\1\uffff\44\54\1\uffff\17\54\2\uffff\1\54\60\uffff\42\54\1\uffff"+ + "\5\54\1\uffff\2\54\1\uffff\7\54\3\uffff\4\54\6\uffff\32\54\106\uffff"+ + "\46\54\12\uffff\51\54\2\uffff\1\54\4\uffff\132\54\5\uffff\104\54\5\uffff"+ + "\122\54\6\uffff\7\54\1\uffff\77\54\1\uffff\1\54\1\uffff\4\54\2\uffff"+ + "\7\54\1\uffff\1\54\1\uffff\4\54\2\uffff\47\54\1\uffff\1\54\1\uffff\4"+ + "\54\2\uffff\37\54\1\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\1\54"+ + "\1\uffff\4\54\2\uffff\7\54\1\uffff\7\54\1\uffff\27\54\1\uffff\37\54\1"+ + "\uffff\1\54\1\uffff\4\54\2\uffff\7\54\1\uffff\47\54\1\uffff\23\54\6\uffff"+ + "\34\54\43\uffff\125\54\14\uffff\u0276\54\12\uffff\32\54\5\uffff\121\54"+ + "\17\uffff\15\54\1\uffff\7\54\13\uffff\27\54\11\uffff\24\54\14\uffff\15"+ + "\54\1\uffff\3\54\1\uffff\2\54\14\uffff\64\54\2\uffff\50\54\2\uffff\12"+ + "\54\6\uffff\12\54\6\uffff\16\54\2\uffff\12\54\6\uffff\130\54\10\uffff"+ + "\52\54\126\uffff\35\54\3\uffff\14\54\4\uffff\14\54\4\uffff\1\54\3\uffff"+ + "\52\54\2\uffff\5\54\153\uffff\40\54\u0300\uffff\154\54\u0094\uffff\u009c"+ + "\54\4\uffff\132\54\6\uffff\26\54\2\uffff\6\54\2\uffff\46\54\2\uffff\6"+ + "\54\2\uffff\10\54\1\uffff\1\54\1\uffff\1\54\1\uffff\1\54\1\uffff\37\54"+ + "\2\uffff\65\54\1\uffff\7\54\1\uffff\1\54\3\uffff\3\54\1\uffff\7\54\3"+ + "\uffff\4\54\2\uffff\6\54\4\uffff\15\54\5\uffff\3\54\1\uffff\7\54\23\uffff"+ + "\10\54\10\uffff\10\54\10\uffff\11\54\2\uffff\12\54\2\uffff\16\54\2\uffff"+ + "\1\54\30\uffff\2\54\2\uffff\11\54\2\uffff\16\54\23\uffff\22\54\36\uffff"+ + "\33\54\25\uffff\74\54\1\uffff\17\54\7\uffff\61\54\14\uffff\u0199\54\2"+ + "\uffff\u0089\54\2\uffff\33\54\57\uffff\47\54\31\uffff\13\54\25\uffff"+ + "\u01b8\54\1\uffff\145\54\2\uffff\22\54\16\uffff\2\54\137\uffff\4\54\1"+ + "\uffff\4\54\2\uffff\34\54\1\uffff\43\54\1\uffff\1\54\1\uffff\4\54\3\uffff"+ + "\1\54\1\uffff\7\54\2\uffff\7\54\16\uffff\37\54\3\uffff\30\54\1\uffff"+ + "\16\54\21\uffff\26\54\12\uffff\u0193\54\26\uffff\77\54\4\uffff\40\54"+ + "\2\uffff\u0110\54\u0372\uffff\32\54\1\uffff\131\54\14\uffff\u00d6\54"+ + "\32\uffff\14\54\5\uffff\7\54\12\uffff\2\54\10\uffff\1\54\3\uffff\40\54"+ + "\1\uffff\126\54\2\uffff\2\54\2\uffff\143\54\5\uffff\50\54\4\uffff\136"+ + "\54\1\uffff\50\54\70\uffff\57\54\1\uffff\44\54\14\uffff\56\54\1\uffff"+ + "\u0080\54\1\uffff\u1ab6\54\12\uffff\u51e6\54\132\uffff\u048d\54\3\uffff"+ + "\67\54\u0739\uffff\u2ba4\54\u215c\uffff\u012e\54\2\uffff\73\54\u0095"+ + "\uffff\7\54\14\uffff\5\54\5\uffff\32\54\1\uffff\5\54\1\uffff\1\54\1\uffff"+ + "\2\54\1\uffff\2\54\1\uffff\154\54\41\uffff\u016b\54\22\uffff\100\54\2"+ + "\uffff\66\54\50\uffff\16\54\2\uffff\20\54\20\uffff\4\54\14\uffff\5\54"+ + "\20\uffff\2\54\2\uffff\12\54\1\uffff\5\54\6\uffff\10\54\1\uffff\4\54"+ + "\4\uffff\5\54\1\uffff\u0087\54\4\uffff\7\54\2\uffff\61\54\1\uffff\1\54"+ + "\2\uffff\1\54\1\uffff\32\54\1\uffff\1\54\1\uffff\1\54\2\uffff\1\54\2"+ + "\uffff\133\54\3\uffff\6\54\2\uffff\6\54\2\uffff\6\54\2\uffff\3\54\3\uffff"+ + "\3\54\1\uffff\3\54\1\uffff\7\54" + }; + + static final short[] DFA63_eot = DFA.unpackEncodedString(DFA63_eotS); + static final short[] DFA63_eof = DFA.unpackEncodedString(DFA63_eofS); + static final char[] DFA63_min = DFA.unpackEncodedStringToUnsignedChars(DFA63_minS); + static final char[] DFA63_max = DFA.unpackEncodedStringToUnsignedChars(DFA63_maxS); + static final short[] DFA63_accept = DFA.unpackEncodedString(DFA63_acceptS); + static final short[] DFA63_special = DFA.unpackEncodedString(DFA63_specialS); + static final short[][] DFA63_transition; + + static { + int numStates = DFA63_transitionS.length; + DFA63_transition = new short[numStates][]; + for (int i=0; i= '\u0000' && LA63_41 <= 't')||(LA63_41 >= 'v' && LA63_41 <= '\uFFFF')) ) {s = 74;} + if ( s>=0 ) return s; + break; + + case 1 : + int LA63_55 = input.LA(1); + s = -1; + if ( (LA63_55=='u') ) {s = 82;} + else if ( ((LA63_55 >= '\u0000' && LA63_55 <= 't')||(LA63_55 >= 'v' && LA63_55 <= '\uFFFF')) ) {s = 83;} + if ( s>=0 ) return s; + break; + + case 2 : + int LA63_174 = input.LA(1); + s = -1; + if ( (LA63_174=='u') ) {s = 194;} + else if ( ((LA63_174 >= '\u0000' && LA63_174 <= 't')||(LA63_174 >= 'v' && LA63_174 <= '\uFFFF')) ) {s = 195;} + if ( s>=0 ) return s; + break; + + case 3 : + int LA63_32 = input.LA(1); + s = -1; + if ( (LA63_32=='u') ) {s = 68;} + else if ( ((LA63_32 >= '\u0000' && LA63_32 <= 't')||(LA63_32 >= 'v' && LA63_32 <= '\uFFFF')) ) {s = 69;} + if ( s>=0 ) return s; + break; + + case 4 : + int LA63_67 = input.LA(1); + s = -1; + if ( (LA63_67=='u') ) {s = 88;} + else if ( ((LA63_67 >= '\u0000' && LA63_67 <= 't')||(LA63_67 >= 'v' && LA63_67 <= '\uFFFF')) ) {s = 89;} + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 63, _s, input); + error(nvae); + throw nvae; + } + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTSParser.java b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTSParser.java new file mode 100644 index 0000000000..11c96dedca --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTSParser.java @@ -0,0 +1,26411 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +// $ANTLR 3.5.2 W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g 2015-06-18 19:37:48 + +package org.alfresco.repo.search.impl.parsers; + + +import org.antlr.runtime.*; +import java.util.Stack; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; + +import org.antlr.runtime.tree.*; + + +@SuppressWarnings("all") +public class FTSParser extends Parser { + public static final String[] tokenNames = new String[] { + "", "", "", "", "AMP", "AND", "AT", "BAR", "BOOST", + "CARAT", "COLON", "COMMA", "CONJUNCTION", "DATETIME", "DAY", "DECIMAL_INTEGER_LITERAL", + "DECIMAL_NUMERAL", "DEFAULT", "DIGIT", "DISJUNCTION", "DOLLAR", "DOT", + "DOTDOT", "E", "EQUALS", "EXACT_PHRASE", "EXACT_TERM", "EXCLAMATION", + "EXCLUDE", "EXCLUSIVE", "EXPONENT", "FG_EXACT_PHRASE", "FG_EXACT_TERM", + "FG_PHRASE", "FG_PROXIMITY", "FG_RANGE", "FG_SYNONYM", "FG_TERM", "FIELD_CONJUNCTION", + "FIELD_DEFAULT", "FIELD_DISJUNCTION", "FIELD_EXCLUDE", "FIELD_GROUP", + "FIELD_MANDATORY", "FIELD_NEGATION", "FIELD_OPTIONAL", "FIELD_REF", "FLOATING_POINT_LITERAL", + "FS", "FTS", "FTSPHRASE", "FTSPRE", "FTSWILD", "FTSWORD", "FUZZY", "F_ESC", + "F_HEX", "F_URI_ALPHA", "F_URI_DIGIT", "F_URI_ESC", "F_URI_OTHER", "GT", + "HOUR", "ID", "INCLUSIVE", "IN_WORD", "LCURL", "LPAREN", "LSQUARE", "LT", + "MANDATORY", "MILLIS", "MINUS", "MINUTE", "MONTH", "NAME_SPACE", "NEGATION", + "NON_ZERO_DIGIT", "NOT", "NOW", "OPTIONAL", "OR", "PERCENT", "PHRASE", + "PLUS", "PREFIX", "PROXIMITY", "QUALIFIER", "QUESTION_MARK", "RANGE", + "RCURL", "RPAREN", "RSQUARE", "SECOND", "SIGNED_INTEGER", "SPECIFICDATETIME", + "STAR", "START_WORD", "SYNONYM", "TEMPLATE", "TERM", "TILDA", "TO", "UNIT", + "URI", "WS", "YEAR", "ZERO_DIGIT" + }; + public static final int EOF=-1; + public static final int AMP=4; + public static final int AND=5; + public static final int AT=6; + public static final int BAR=7; + public static final int BOOST=8; + public static final int CARAT=9; + public static final int COLON=10; + public static final int COMMA=11; + public static final int CONJUNCTION=12; + public static final int DATETIME=13; + public static final int DAY=14; + public static final int DECIMAL_INTEGER_LITERAL=15; + public static final int DECIMAL_NUMERAL=16; + public static final int DEFAULT=17; + public static final int DIGIT=18; + public static final int DISJUNCTION=19; + public static final int DOLLAR=20; + public static final int DOT=21; + public static final int DOTDOT=22; + public static final int E=23; + public static final int EQUALS=24; + public static final int EXACT_PHRASE=25; + public static final int EXACT_TERM=26; + public static final int EXCLAMATION=27; + public static final int EXCLUDE=28; + public static final int EXCLUSIVE=29; + public static final int EXPONENT=30; + public static final int FG_EXACT_PHRASE=31; + public static final int FG_EXACT_TERM=32; + public static final int FG_PHRASE=33; + public static final int FG_PROXIMITY=34; + public static final int FG_RANGE=35; + public static final int FG_SYNONYM=36; + public static final int FG_TERM=37; + public static final int FIELD_CONJUNCTION=38; + public static final int FIELD_DEFAULT=39; + public static final int FIELD_DISJUNCTION=40; + public static final int FIELD_EXCLUDE=41; + public static final int FIELD_GROUP=42; + public static final int FIELD_MANDATORY=43; + public static final int FIELD_NEGATION=44; + public static final int FIELD_OPTIONAL=45; + public static final int FIELD_REF=46; + public static final int FLOATING_POINT_LITERAL=47; + public static final int FS=48; + public static final int FTS=49; + public static final int FTSPHRASE=50; + public static final int FTSPRE=51; + public static final int FTSWILD=52; + public static final int FTSWORD=53; + public static final int FUZZY=54; + public static final int F_ESC=55; + public static final int F_HEX=56; + public static final int F_URI_ALPHA=57; + public static final int F_URI_DIGIT=58; + public static final int F_URI_ESC=59; + public static final int F_URI_OTHER=60; + public static final int GT=61; + public static final int HOUR=62; + public static final int ID=63; + public static final int INCLUSIVE=64; + public static final int IN_WORD=65; + public static final int LCURL=66; + public static final int LPAREN=67; + public static final int LSQUARE=68; + public static final int LT=69; + public static final int MANDATORY=70; + public static final int MILLIS=71; + public static final int MINUS=72; + public static final int MINUTE=73; + public static final int MONTH=74; + public static final int NAME_SPACE=75; + public static final int NEGATION=76; + public static final int NON_ZERO_DIGIT=77; + public static final int NOT=78; + public static final int NOW=79; + public static final int OPTIONAL=80; + public static final int OR=81; + public static final int PERCENT=82; + public static final int PHRASE=83; + public static final int PLUS=84; + public static final int PREFIX=85; + public static final int PROXIMITY=86; + public static final int QUALIFIER=87; + public static final int QUESTION_MARK=88; + public static final int RANGE=89; + public static final int RCURL=90; + public static final int RPAREN=91; + public static final int RSQUARE=92; + public static final int SECOND=93; + public static final int SIGNED_INTEGER=94; + public static final int SPECIFICDATETIME=95; + public static final int STAR=96; + public static final int START_WORD=97; + public static final int SYNONYM=98; + public static final int TEMPLATE=99; + public static final int TERM=100; + public static final int TILDA=101; + public static final int TO=102; + public static final int UNIT=103; + public static final int URI=104; + public static final int WS=105; + public static final int YEAR=106; + public static final int ZERO_DIGIT=107; + + // delegates + public Parser[] getDelegates() { + return new Parser[] {}; + } + + // delegators + + + public FTSParser(TokenStream input) { + this(input, new RecognizerSharedState()); + } + public FTSParser(TokenStream input, RecognizerSharedState state) { + super(input, state); + } + + protected TreeAdaptor adaptor = new CommonTreeAdaptor(); + + public void setTreeAdaptor(TreeAdaptor adaptor) { + this.adaptor = adaptor; + } + public TreeAdaptor getTreeAdaptor() { + return adaptor; + } + @Override public String[] getTokenNames() { return FTSParser.tokenNames; } + @Override public String getGrammarFileName() { return "W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g"; } + + + public enum Mode + { + CMIS, DEFAULT_CONJUNCTION, DEFAULT_DISJUNCTION + } + + private Stack paraphrases = new Stack(); + + private boolean defaultFieldConjunction = true; + + private Mode mode = Mode.DEFAULT_CONJUNCTION; + + public Mode getMode() + { + return mode; + } + + public void setMode(Mode mode) + { + this.mode = mode; + } + + public boolean defaultFieldConjunction() + { + return defaultFieldConjunction; + } + + public void setDefaultFieldConjunction(boolean defaultFieldConjunction) + { + this.defaultFieldConjunction = defaultFieldConjunction; + } + + protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException + { + throw new MismatchedTokenException(ttype, input); + } + + public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException + { + throw e; + } + + public String getErrorMessage(RecognitionException e, String[] tokenNames) + { + List stack = getRuleInvocationStack(e, this.getClass().getName()); + String msg = e.getMessage(); + if ( e instanceof UnwantedTokenException ) + { + UnwantedTokenException ute = (UnwantedTokenException)e; + String tokenName=""; + if ( ute.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[ute.expecting]; + } + msg = "extraneous input " + getTokenErrorDisplay(ute.getUnexpectedToken()) + + " expecting "+tokenName; + } + else if ( e instanceof MissingTokenException ) + { + MissingTokenException mte = (MissingTokenException)e; + String tokenName=""; + if ( mte.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mte.expecting]; + } + msg = "missing " + tokenName+" at " + getTokenErrorDisplay(e.token) + + " (" + getLongTokenErrorDisplay(e.token) +")"; + } + else if ( e instanceof MismatchedTokenException ) + { + MismatchedTokenException mte = (MismatchedTokenException)e; + String tokenName=""; + if ( mte.expecting== Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mte.expecting]; + } + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting " + tokenName +" (" + getLongTokenErrorDisplay(e.token) + ")"; + } + else if ( e instanceof MismatchedTreeNodeException ) + { + MismatchedTreeNodeException mtne = (MismatchedTreeNodeException)e; + String tokenName=""; + if ( mtne.expecting==Token.EOF ) + { + tokenName = "EOF"; + } + else + { + tokenName = tokenNames[mtne.expecting]; + } + msg = "mismatched tree node: " + mtne.node + " expecting " + tokenName; + } + else if ( e instanceof NoViableAltException ) + { + NoViableAltException nvae = (NoViableAltException)e; + msg = "no viable alternative at input " + getTokenErrorDisplay(e.token) + + "\n\t (decision=" + nvae.decisionNumber + + " state " + nvae.stateNumber + ")" + + " decision=<<" + nvae.grammarDecisionDescription + ">>"; + } + else if ( e instanceof EarlyExitException ) + { + //EarlyExitException eee = (EarlyExitException)e; + // for development, can add "(decision="+eee.decisionNumber+")" + msg = "required (...)+ loop did not match anything at input " + getTokenErrorDisplay(e.token); + } + else if ( e instanceof MismatchedSetException ) + { + MismatchedSetException mse = (MismatchedSetException)e; + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting set " + mse.expecting; + } + else if ( e instanceof MismatchedNotSetException ) + { + MismatchedNotSetException mse = (MismatchedNotSetException)e; + msg = "mismatched input " + getTokenErrorDisplay(e.token) + + " expecting set " + mse.expecting; + } + else if ( e instanceof FailedPredicateException ) + { + FailedPredicateException fpe = (FailedPredicateException)e; + msg = "rule " + fpe.ruleName + " failed predicate: {" + fpe.predicateText + "}?"; + } + + if(paraphrases.size() > 0) + { + String paraphrase = (String)paraphrases.peek(); + msg = msg+" "+paraphrase; + } + return msg +"\n\t"+stack; + } + + public String getLongTokenErrorDisplay(Token t) + { + return t.toString(); + } + + + public String getErrorString(RecognitionException e) + { + String hdr = getErrorHeader(e); + String msg = getErrorMessage(e, this.getTokenNames()); + return hdr+" "+msg; + } + + + public static class ftsQuery_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsQuery" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:342:1: ftsQuery : ftsDisjunction EOF -> ftsDisjunction ; + public final FTSParser.ftsQuery_return ftsQuery() throws RecognitionException { + FTSParser.ftsQuery_return retval = new FTSParser.ftsQuery_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token EOF2=null; + ParserRuleReturnScope ftsDisjunction1 =null; + + Object EOF2_tree=null; + RewriteRuleTokenStream stream_EOF=new RewriteRuleTokenStream(adaptor,"token EOF"); + RewriteRuleSubtreeStream stream_ftsDisjunction=new RewriteRuleSubtreeStream(adaptor,"rule ftsDisjunction"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:343:9: ( ftsDisjunction EOF -> ftsDisjunction ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:344:9: ftsDisjunction EOF + { + pushFollow(FOLLOW_ftsDisjunction_in_ftsQuery577); + ftsDisjunction1=ftsDisjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsDisjunction.add(ftsDisjunction1.getTree()); + EOF2=(Token)match(input,EOF,FOLLOW_EOF_in_ftsQuery579); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_EOF.add(EOF2); + + // AST REWRITE + // elements: ftsDisjunction + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 345:17: -> ftsDisjunction + { + adaptor.addChild(root_0, stream_ftsDisjunction.nextTree()); + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsQuery" + + + public static class ftsDisjunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsDisjunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:353:1: ftsDisjunction : ({...}? cmisExplicitDisjunction |{...}? ftsExplicitDisjunction |{...}? ftsImplicitDisjunction ); + public final FTSParser.ftsDisjunction_return ftsDisjunction() throws RecognitionException { + FTSParser.ftsDisjunction_return retval = new FTSParser.ftsDisjunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope cmisExplicitDisjunction3 =null; + ParserRuleReturnScope ftsExplicitDisjunction4 =null; + ParserRuleReturnScope ftsImplicitDisjunction5 =null; + + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:354:9: ({...}? cmisExplicitDisjunction |{...}? ftsExplicitDisjunction |{...}? ftsImplicitDisjunction ) + int alt1=3; + switch ( input.LA(1) ) { + case COMMA: + case DOT: + { + int LA1_1 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 1, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case ID: + { + int LA1_2 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 2, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case FTSWORD: + { + int LA1_3 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 3, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case FTSPRE: + { + int LA1_4 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 4, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case FTSWILD: + { + int LA1_5 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 5, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case NOT: + { + int LA1_6 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 6, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case TO: + { + int LA1_7 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 7, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case DECIMAL_INTEGER_LITERAL: + { + int LA1_8 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 8, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case FLOATING_POINT_LITERAL: + { + int LA1_9 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 9, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case STAR: + { + int LA1_10 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 10, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case QUESTION_MARK: + { + int LA1_11 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 11, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case DATETIME: + { + int LA1_12 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 12, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case URI: + { + int LA1_13 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 13, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case FTSPHRASE: + { + int LA1_14 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 14, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case MINUS: + { + int LA1_15 = input.LA(2); + if ( ((getMode() == Mode.CMIS)) ) { + alt1=1; + } + else if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 15, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case AND: + { + int LA1_16 = input.LA(2); + if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 16, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case AMP: + { + alt1=2; + } + break; + case EXCLAMATION: + { + int LA1_18 = input.LA(2); + if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 18, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case AT: + { + int LA1_19 = input.LA(2); + if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 19, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case OR: + { + int LA1_20 = input.LA(2); + if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 20, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case LSQUARE: + { + int LA1_21 = input.LA(2); + if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 21, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case LT: + { + int LA1_22 = input.LA(2); + if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 22, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case EQUALS: + { + int LA1_23 = input.LA(2); + if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 23, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case TILDA: + { + int LA1_24 = input.LA(2); + if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 24, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case LPAREN: + { + int LA1_25 = input.LA(2); + if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 25, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case PERCENT: + { + int LA1_26 = input.LA(2); + if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 26, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case PLUS: + { + int LA1_27 = input.LA(2); + if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 27, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case BAR: + { + int LA1_28 = input.LA(2); + if ( ((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + alt1=2; + } + else if ( ((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + alt1=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 1, 28, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 1, 0, input); + throw nvae; + } + switch (alt1) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:355:11: {...}? cmisExplicitDisjunction + { + root_0 = (Object)adaptor.nil(); + + + if ( !((getMode() == Mode.CMIS)) ) { + if (state.backtracking>0) {state.failed=true; return retval;} + throw new FailedPredicateException(input, "ftsDisjunction", "getMode() == Mode.CMIS"); + } + pushFollow(FOLLOW_cmisExplicitDisjunction_in_ftsDisjunction639); + cmisExplicitDisjunction3=cmisExplicitDisjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, cmisExplicitDisjunction3.getTree()); + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:356:11: {...}? ftsExplicitDisjunction + { + root_0 = (Object)adaptor.nil(); + + + if ( !((getMode() == Mode.DEFAULT_CONJUNCTION)) ) { + if (state.backtracking>0) {state.failed=true; return retval;} + throw new FailedPredicateException(input, "ftsDisjunction", "getMode() == Mode.DEFAULT_CONJUNCTION"); + } + pushFollow(FOLLOW_ftsExplicitDisjunction_in_ftsDisjunction653); + ftsExplicitDisjunction4=ftsExplicitDisjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsExplicitDisjunction4.getTree()); + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:357:11: {...}? ftsImplicitDisjunction + { + root_0 = (Object)adaptor.nil(); + + + if ( !((getMode() == Mode.DEFAULT_DISJUNCTION)) ) { + if (state.backtracking>0) {state.failed=true; return retval;} + throw new FailedPredicateException(input, "ftsDisjunction", "getMode() == Mode.DEFAULT_DISJUNCTION"); + } + pushFollow(FOLLOW_ftsImplicitDisjunction_in_ftsDisjunction667); + ftsImplicitDisjunction5=ftsImplicitDisjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsImplicitDisjunction5.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsDisjunction" + + + public static class ftsExplicitDisjunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsExplicitDisjunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:360:1: ftsExplicitDisjunction : ftsImplicitConjunction ( or ftsImplicitConjunction )* -> ^( DISJUNCTION ( ftsImplicitConjunction )+ ) ; + public final FTSParser.ftsExplicitDisjunction_return ftsExplicitDisjunction() throws RecognitionException { + FTSParser.ftsExplicitDisjunction_return retval = new FTSParser.ftsExplicitDisjunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope ftsImplicitConjunction6 =null; + ParserRuleReturnScope or7 =null; + ParserRuleReturnScope ftsImplicitConjunction8 =null; + + RewriteRuleSubtreeStream stream_or=new RewriteRuleSubtreeStream(adaptor,"rule or"); + RewriteRuleSubtreeStream stream_ftsImplicitConjunction=new RewriteRuleSubtreeStream(adaptor,"rule ftsImplicitConjunction"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:361:9: ( ftsImplicitConjunction ( or ftsImplicitConjunction )* -> ^( DISJUNCTION ( ftsImplicitConjunction )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:362:9: ftsImplicitConjunction ( or ftsImplicitConjunction )* + { + pushFollow(FOLLOW_ftsImplicitConjunction_in_ftsExplicitDisjunction700); + ftsImplicitConjunction6=ftsImplicitConjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsImplicitConjunction.add(ftsImplicitConjunction6.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:362:32: ( or ftsImplicitConjunction )* + loop2: + while (true) { + int alt2=2; + int LA2_0 = input.LA(1); + if ( (LA2_0==BAR||LA2_0==OR) ) { + alt2=1; + } + + switch (alt2) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:362:33: or ftsImplicitConjunction + { + pushFollow(FOLLOW_or_in_ftsExplicitDisjunction703); + or7=or(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_or.add(or7.getTree()); + pushFollow(FOLLOW_ftsImplicitConjunction_in_ftsExplicitDisjunction705); + ftsImplicitConjunction8=ftsImplicitConjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsImplicitConjunction.add(ftsImplicitConjunction8.getTree()); + } + break; + + default : + break loop2; + } + } + + // AST REWRITE + // elements: ftsImplicitConjunction + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 363:17: -> ^( DISJUNCTION ( ftsImplicitConjunction )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:364:25: ^( DISJUNCTION ( ftsImplicitConjunction )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(DISJUNCTION, "DISJUNCTION"), root_1); + if ( !(stream_ftsImplicitConjunction.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_ftsImplicitConjunction.hasNext() ) { + adaptor.addChild(root_1, stream_ftsImplicitConjunction.nextTree()); + } + stream_ftsImplicitConjunction.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsExplicitDisjunction" + + + public static class cmisExplicitDisjunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "cmisExplicitDisjunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:367:1: cmisExplicitDisjunction : cmisConjunction ( or cmisConjunction )* -> ^( DISJUNCTION ( cmisConjunction )+ ) ; + public final FTSParser.cmisExplicitDisjunction_return cmisExplicitDisjunction() throws RecognitionException { + FTSParser.cmisExplicitDisjunction_return retval = new FTSParser.cmisExplicitDisjunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope cmisConjunction9 =null; + ParserRuleReturnScope or10 =null; + ParserRuleReturnScope cmisConjunction11 =null; + + RewriteRuleSubtreeStream stream_cmisConjunction=new RewriteRuleSubtreeStream(adaptor,"rule cmisConjunction"); + RewriteRuleSubtreeStream stream_or=new RewriteRuleSubtreeStream(adaptor,"rule or"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:368:9: ( cmisConjunction ( or cmisConjunction )* -> ^( DISJUNCTION ( cmisConjunction )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:369:9: cmisConjunction ( or cmisConjunction )* + { + pushFollow(FOLLOW_cmisConjunction_in_cmisExplicitDisjunction789); + cmisConjunction9=cmisConjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_cmisConjunction.add(cmisConjunction9.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:369:25: ( or cmisConjunction )* + loop3: + while (true) { + int alt3=2; + int LA3_0 = input.LA(1); + if ( (LA3_0==BAR||LA3_0==OR) ) { + alt3=1; + } + + switch (alt3) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:369:26: or cmisConjunction + { + pushFollow(FOLLOW_or_in_cmisExplicitDisjunction792); + or10=or(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_or.add(or10.getTree()); + pushFollow(FOLLOW_cmisConjunction_in_cmisExplicitDisjunction794); + cmisConjunction11=cmisConjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_cmisConjunction.add(cmisConjunction11.getTree()); + } + break; + + default : + break loop3; + } + } + + // AST REWRITE + // elements: cmisConjunction + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 370:17: -> ^( DISJUNCTION ( cmisConjunction )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:371:25: ^( DISJUNCTION ( cmisConjunction )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(DISJUNCTION, "DISJUNCTION"), root_1); + if ( !(stream_cmisConjunction.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_cmisConjunction.hasNext() ) { + adaptor.addChild(root_1, stream_cmisConjunction.nextTree()); + } + stream_cmisConjunction.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "cmisExplicitDisjunction" + + + public static class ftsImplicitDisjunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsImplicitDisjunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:374:1: ftsImplicitDisjunction : ( ( or )? ftsExplicitConjunction )+ -> ^( DISJUNCTION ( ftsExplicitConjunction )+ ) ; + public final FTSParser.ftsImplicitDisjunction_return ftsImplicitDisjunction() throws RecognitionException { + FTSParser.ftsImplicitDisjunction_return retval = new FTSParser.ftsImplicitDisjunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope or12 =null; + ParserRuleReturnScope ftsExplicitConjunction13 =null; + + RewriteRuleSubtreeStream stream_or=new RewriteRuleSubtreeStream(adaptor,"rule or"); + RewriteRuleSubtreeStream stream_ftsExplicitConjunction=new RewriteRuleSubtreeStream(adaptor,"rule ftsExplicitConjunction"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:375:9: ( ( ( or )? ftsExplicitConjunction )+ -> ^( DISJUNCTION ( ftsExplicitConjunction )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:376:9: ( ( or )? ftsExplicitConjunction )+ + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:376:9: ( ( or )? ftsExplicitConjunction )+ + int cnt5=0; + loop5: + while (true) { + int alt5=2; + int LA5_0 = input.LA(1); + if ( ((LA5_0 >= AND && LA5_0 <= BAR)||LA5_0==COMMA||LA5_0==DATETIME||LA5_0==DECIMAL_INTEGER_LITERAL||LA5_0==DOT||LA5_0==EQUALS||LA5_0==EXCLAMATION||LA5_0==FLOATING_POINT_LITERAL||(LA5_0 >= FTSPHRASE && LA5_0 <= FTSWORD)||LA5_0==ID||(LA5_0 >= LPAREN && LA5_0 <= LT)||LA5_0==MINUS||LA5_0==NOT||(LA5_0 >= OR && LA5_0 <= PERCENT)||LA5_0==PLUS||LA5_0==QUESTION_MARK||LA5_0==STAR||(LA5_0 >= TILDA && LA5_0 <= TO)||LA5_0==URI) ) { + alt5=1; + } + + switch (alt5) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:376:10: ( or )? ftsExplicitConjunction + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:376:10: ( or )? + int alt4=2; + int LA4_0 = input.LA(1); + if ( (LA4_0==OR) ) { + int LA4_1 = input.LA(2); + if ( ((LA4_1 >= AND && LA4_1 <= BAR)||LA4_1==COMMA||LA4_1==DATETIME||LA4_1==DECIMAL_INTEGER_LITERAL||LA4_1==DOT||LA4_1==EQUALS||LA4_1==EXCLAMATION||LA4_1==FLOATING_POINT_LITERAL||(LA4_1 >= FTSPHRASE && LA4_1 <= FTSWORD)||LA4_1==ID||(LA4_1 >= LPAREN && LA4_1 <= LT)||LA4_1==MINUS||LA4_1==NOT||(LA4_1 >= OR && LA4_1 <= PERCENT)||LA4_1==PLUS||LA4_1==QUESTION_MARK||LA4_1==STAR||(LA4_1 >= TILDA && LA4_1 <= TO)||LA4_1==URI) ) { + alt4=1; + } + } + else if ( (LA4_0==BAR) ) { + int LA4_2 = input.LA(2); + if ( (LA4_2==BAR) ) { + alt4=1; + } + } + switch (alt4) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:376:10: or + { + pushFollow(FOLLOW_or_in_ftsImplicitDisjunction879); + or12=or(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_or.add(or12.getTree()); + } + break; + + } + + pushFollow(FOLLOW_ftsExplicitConjunction_in_ftsImplicitDisjunction882); + ftsExplicitConjunction13=ftsExplicitConjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsExplicitConjunction.add(ftsExplicitConjunction13.getTree()); + } + break; + + default : + if ( cnt5 >= 1 ) break loop5; + if (state.backtracking>0) {state.failed=true; return retval;} + EarlyExitException eee = new EarlyExitException(5, input); + throw eee; + } + cnt5++; + } + + // AST REWRITE + // elements: ftsExplicitConjunction + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 377:17: -> ^( DISJUNCTION ( ftsExplicitConjunction )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:378:25: ^( DISJUNCTION ( ftsExplicitConjunction )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(DISJUNCTION, "DISJUNCTION"), root_1); + if ( !(stream_ftsExplicitConjunction.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_ftsExplicitConjunction.hasNext() ) { + adaptor.addChild(root_1, stream_ftsExplicitConjunction.nextTree()); + } + stream_ftsExplicitConjunction.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsImplicitDisjunction" + + + public static class ftsExplicitConjunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsExplicitConjunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:385:1: ftsExplicitConjunction : ftsPrefixed ( and ftsPrefixed )* -> ^( CONJUNCTION ( ftsPrefixed )+ ) ; + public final FTSParser.ftsExplicitConjunction_return ftsExplicitConjunction() throws RecognitionException { + FTSParser.ftsExplicitConjunction_return retval = new FTSParser.ftsExplicitConjunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope ftsPrefixed14 =null; + ParserRuleReturnScope and15 =null; + ParserRuleReturnScope ftsPrefixed16 =null; + + RewriteRuleSubtreeStream stream_and=new RewriteRuleSubtreeStream(adaptor,"rule and"); + RewriteRuleSubtreeStream stream_ftsPrefixed=new RewriteRuleSubtreeStream(adaptor,"rule ftsPrefixed"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:386:9: ( ftsPrefixed ( and ftsPrefixed )* -> ^( CONJUNCTION ( ftsPrefixed )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:387:9: ftsPrefixed ( and ftsPrefixed )* + { + pushFollow(FOLLOW_ftsPrefixed_in_ftsExplicitConjunction969); + ftsPrefixed14=ftsPrefixed(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsPrefixed.add(ftsPrefixed14.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:387:21: ( and ftsPrefixed )* + loop6: + while (true) { + int alt6=2; + int LA6_0 = input.LA(1); + if ( (LA6_0==AND) ) { + int LA6_2 = input.LA(2); + if ( ((LA6_2 >= AND && LA6_2 <= BAR)||LA6_2==COMMA||LA6_2==DATETIME||LA6_2==DECIMAL_INTEGER_LITERAL||LA6_2==DOT||LA6_2==EQUALS||LA6_2==EXCLAMATION||LA6_2==FLOATING_POINT_LITERAL||(LA6_2 >= FTSPHRASE && LA6_2 <= FTSWORD)||LA6_2==ID||(LA6_2 >= LPAREN && LA6_2 <= LT)||LA6_2==MINUS||LA6_2==NOT||(LA6_2 >= OR && LA6_2 <= PERCENT)||LA6_2==PLUS||LA6_2==QUESTION_MARK||LA6_2==STAR||(LA6_2 >= TILDA && LA6_2 <= TO)||LA6_2==URI) ) { + alt6=1; + } + + } + else if ( (LA6_0==AMP) ) { + alt6=1; + } + + switch (alt6) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:387:22: and ftsPrefixed + { + pushFollow(FOLLOW_and_in_ftsExplicitConjunction972); + and15=and(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_and.add(and15.getTree()); + pushFollow(FOLLOW_ftsPrefixed_in_ftsExplicitConjunction974); + ftsPrefixed16=ftsPrefixed(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsPrefixed.add(ftsPrefixed16.getTree()); + } + break; + + default : + break loop6; + } + } + + // AST REWRITE + // elements: ftsPrefixed + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 388:17: -> ^( CONJUNCTION ( ftsPrefixed )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:389:25: ^( CONJUNCTION ( ftsPrefixed )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(CONJUNCTION, "CONJUNCTION"), root_1); + if ( !(stream_ftsPrefixed.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_ftsPrefixed.hasNext() ) { + adaptor.addChild(root_1, stream_ftsPrefixed.nextTree()); + } + stream_ftsPrefixed.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsExplicitConjunction" + + + public static class ftsImplicitConjunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsImplicitConjunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:392:1: ftsImplicitConjunction : ( ( and )? ftsPrefixed )+ -> ^( CONJUNCTION ( ftsPrefixed )+ ) ; + public final FTSParser.ftsImplicitConjunction_return ftsImplicitConjunction() throws RecognitionException { + FTSParser.ftsImplicitConjunction_return retval = new FTSParser.ftsImplicitConjunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope and17 =null; + ParserRuleReturnScope ftsPrefixed18 =null; + + RewriteRuleSubtreeStream stream_and=new RewriteRuleSubtreeStream(adaptor,"rule and"); + RewriteRuleSubtreeStream stream_ftsPrefixed=new RewriteRuleSubtreeStream(adaptor,"rule ftsPrefixed"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:393:9: ( ( ( and )? ftsPrefixed )+ -> ^( CONJUNCTION ( ftsPrefixed )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:394:9: ( ( and )? ftsPrefixed )+ + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:394:9: ( ( and )? ftsPrefixed )+ + int cnt8=0; + loop8: + while (true) { + int alt8=2; + switch ( input.LA(1) ) { + case OR: + { + int LA8_1 = input.LA(2); + if ( (LA8_1==COLON) ) { + alt8=1; + } + + } + break; + case BAR: + { + int LA8_2 = input.LA(2); + if ( ((LA8_2 >= AND && LA8_2 <= AT)||LA8_2==COMMA||LA8_2==DATETIME||LA8_2==DECIMAL_INTEGER_LITERAL||LA8_2==DOT||LA8_2==EQUALS||LA8_2==FLOATING_POINT_LITERAL||(LA8_2 >= FTSPHRASE && LA8_2 <= FTSWORD)||LA8_2==ID||(LA8_2 >= LPAREN && LA8_2 <= LT)||LA8_2==NOT||(LA8_2 >= OR && LA8_2 <= PERCENT)||LA8_2==QUESTION_MARK||LA8_2==STAR||(LA8_2 >= TILDA && LA8_2 <= TO)||LA8_2==URI) ) { + alt8=1; + } + + } + break; + case AMP: + case AND: + case AT: + case COMMA: + case DATETIME: + case DECIMAL_INTEGER_LITERAL: + case DOT: + case EQUALS: + case EXCLAMATION: + case FLOATING_POINT_LITERAL: + case FTSPHRASE: + case FTSPRE: + case FTSWILD: + case FTSWORD: + case ID: + case LPAREN: + case LSQUARE: + case LT: + case MINUS: + case NOT: + case PERCENT: + case PLUS: + case QUESTION_MARK: + case STAR: + case TILDA: + case TO: + case URI: + { + alt8=1; + } + break; + } + switch (alt8) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:394:10: ( and )? ftsPrefixed + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:394:10: ( and )? + int alt7=2; + int LA7_0 = input.LA(1); + if ( (LA7_0==AND) ) { + int LA7_1 = input.LA(2); + if ( ((LA7_1 >= AND && LA7_1 <= BAR)||LA7_1==COMMA||LA7_1==DATETIME||LA7_1==DECIMAL_INTEGER_LITERAL||LA7_1==DOT||LA7_1==EQUALS||LA7_1==EXCLAMATION||LA7_1==FLOATING_POINT_LITERAL||(LA7_1 >= FTSPHRASE && LA7_1 <= FTSWORD)||LA7_1==ID||(LA7_1 >= LPAREN && LA7_1 <= LT)||LA7_1==MINUS||LA7_1==NOT||(LA7_1 >= OR && LA7_1 <= PERCENT)||LA7_1==PLUS||LA7_1==QUESTION_MARK||LA7_1==STAR||(LA7_1 >= TILDA && LA7_1 <= TO)||LA7_1==URI) ) { + alt7=1; + } + } + else if ( (LA7_0==AMP) ) { + alt7=1; + } + switch (alt7) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:394:10: and + { + pushFollow(FOLLOW_and_in_ftsImplicitConjunction1059); + and17=and(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_and.add(and17.getTree()); + } + break; + + } + + pushFollow(FOLLOW_ftsPrefixed_in_ftsImplicitConjunction1062); + ftsPrefixed18=ftsPrefixed(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsPrefixed.add(ftsPrefixed18.getTree()); + } + break; + + default : + if ( cnt8 >= 1 ) break loop8; + if (state.backtracking>0) {state.failed=true; return retval;} + EarlyExitException eee = new EarlyExitException(8, input); + throw eee; + } + cnt8++; + } + + // AST REWRITE + // elements: ftsPrefixed + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 395:17: -> ^( CONJUNCTION ( ftsPrefixed )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:396:25: ^( CONJUNCTION ( ftsPrefixed )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(CONJUNCTION, "CONJUNCTION"), root_1); + if ( !(stream_ftsPrefixed.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_ftsPrefixed.hasNext() ) { + adaptor.addChild(root_1, stream_ftsPrefixed.nextTree()); + } + stream_ftsPrefixed.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsImplicitConjunction" + + + public static class cmisConjunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "cmisConjunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:399:1: cmisConjunction : ( cmisPrefixed )+ -> ^( CONJUNCTION ( cmisPrefixed )+ ) ; + public final FTSParser.cmisConjunction_return cmisConjunction() throws RecognitionException { + FTSParser.cmisConjunction_return retval = new FTSParser.cmisConjunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope cmisPrefixed19 =null; + + RewriteRuleSubtreeStream stream_cmisPrefixed=new RewriteRuleSubtreeStream(adaptor,"rule cmisPrefixed"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:400:9: ( ( cmisPrefixed )+ -> ^( CONJUNCTION ( cmisPrefixed )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:401:9: ( cmisPrefixed )+ + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:401:9: ( cmisPrefixed )+ + int cnt9=0; + loop9: + while (true) { + int alt9=2; + int LA9_0 = input.LA(1); + if ( (LA9_0==COMMA||LA9_0==DATETIME||LA9_0==DECIMAL_INTEGER_LITERAL||LA9_0==DOT||LA9_0==FLOATING_POINT_LITERAL||(LA9_0 >= FTSPHRASE && LA9_0 <= FTSWORD)||LA9_0==ID||LA9_0==MINUS||LA9_0==NOT||LA9_0==QUESTION_MARK||LA9_0==STAR||LA9_0==TO||LA9_0==URI) ) { + alt9=1; + } + + switch (alt9) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:401:9: cmisPrefixed + { + pushFollow(FOLLOW_cmisPrefixed_in_cmisConjunction1146); + cmisPrefixed19=cmisPrefixed(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_cmisPrefixed.add(cmisPrefixed19.getTree()); + } + break; + + default : + if ( cnt9 >= 1 ) break loop9; + if (state.backtracking>0) {state.failed=true; return retval;} + EarlyExitException eee = new EarlyExitException(9, input); + throw eee; + } + cnt9++; + } + + // AST REWRITE + // elements: cmisPrefixed + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 402:17: -> ^( CONJUNCTION ( cmisPrefixed )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:403:25: ^( CONJUNCTION ( cmisPrefixed )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(CONJUNCTION, "CONJUNCTION"), root_1); + if ( !(stream_cmisPrefixed.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_cmisPrefixed.hasNext() ) { + adaptor.addChild(root_1, stream_cmisPrefixed.nextTree()); + } + stream_cmisPrefixed.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "cmisConjunction" + + + public static class ftsPrefixed_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsPrefixed" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:413:1: ftsPrefixed : ( ( not )=> not ftsTest ( boost )? -> ^( NEGATION ftsTest ( boost )? ) | ftsTest ( boost )? -> ^( DEFAULT ftsTest ( boost )? ) | PLUS ftsTest ( boost )? -> ^( MANDATORY ftsTest ( boost )? ) | BAR ftsTest ( boost )? -> ^( OPTIONAL ftsTest ( boost )? ) | MINUS ftsTest ( boost )? -> ^( EXCLUDE ftsTest ( boost )? ) ); + public final FTSParser.ftsPrefixed_return ftsPrefixed() throws RecognitionException { + FTSParser.ftsPrefixed_return retval = new FTSParser.ftsPrefixed_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token PLUS25=null; + Token BAR28=null; + Token MINUS31=null; + ParserRuleReturnScope not20 =null; + ParserRuleReturnScope ftsTest21 =null; + ParserRuleReturnScope boost22 =null; + ParserRuleReturnScope ftsTest23 =null; + ParserRuleReturnScope boost24 =null; + ParserRuleReturnScope ftsTest26 =null; + ParserRuleReturnScope boost27 =null; + ParserRuleReturnScope ftsTest29 =null; + ParserRuleReturnScope boost30 =null; + ParserRuleReturnScope ftsTest32 =null; + ParserRuleReturnScope boost33 =null; + + Object PLUS25_tree=null; + Object BAR28_tree=null; + Object MINUS31_tree=null; + RewriteRuleTokenStream stream_BAR=new RewriteRuleTokenStream(adaptor,"token BAR"); + RewriteRuleTokenStream stream_PLUS=new RewriteRuleTokenStream(adaptor,"token PLUS"); + RewriteRuleTokenStream stream_MINUS=new RewriteRuleTokenStream(adaptor,"token MINUS"); + RewriteRuleSubtreeStream stream_not=new RewriteRuleSubtreeStream(adaptor,"rule not"); + RewriteRuleSubtreeStream stream_boost=new RewriteRuleSubtreeStream(adaptor,"rule boost"); + RewriteRuleSubtreeStream stream_ftsTest=new RewriteRuleSubtreeStream(adaptor,"rule ftsTest"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:414:9: ( ( not )=> not ftsTest ( boost )? -> ^( NEGATION ftsTest ( boost )? ) | ftsTest ( boost )? -> ^( DEFAULT ftsTest ( boost )? ) | PLUS ftsTest ( boost )? -> ^( MANDATORY ftsTest ( boost )? ) | BAR ftsTest ( boost )? -> ^( OPTIONAL ftsTest ( boost )? ) | MINUS ftsTest ( boost )? -> ^( EXCLUDE ftsTest ( boost )? ) ) + int alt15=5; + int LA15_0 = input.LA(1); + if ( (LA15_0==NOT) ) { + int LA15_1 = input.LA(2); + if ( (synpred1_FTS()) ) { + alt15=1; + } + else if ( (true) ) { + alt15=2; + } + + } + else if ( ((LA15_0 >= AND && LA15_0 <= AT)||LA15_0==COMMA||LA15_0==DATETIME||LA15_0==DECIMAL_INTEGER_LITERAL||LA15_0==DOT||LA15_0==EQUALS||LA15_0==FLOATING_POINT_LITERAL||(LA15_0 >= FTSPHRASE && LA15_0 <= FTSWORD)||LA15_0==ID||(LA15_0 >= LPAREN && LA15_0 <= LT)||(LA15_0 >= OR && LA15_0 <= PERCENT)||LA15_0==QUESTION_MARK||LA15_0==STAR||(LA15_0 >= TILDA && LA15_0 <= TO)||LA15_0==URI) ) { + alt15=2; + } + else if ( (LA15_0==EXCLAMATION) && (synpred1_FTS())) { + alt15=1; + } + else if ( (LA15_0==PLUS) ) { + alt15=3; + } + else if ( (LA15_0==BAR) ) { + alt15=4; + } + else if ( (LA15_0==MINUS) ) { + alt15=5; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 15, 0, input); + throw nvae; + } + + switch (alt15) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:415:9: ( not )=> not ftsTest ( boost )? + { + pushFollow(FOLLOW_not_in_ftsPrefixed1238); + not20=not(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_not.add(not20.getTree()); + pushFollow(FOLLOW_ftsTest_in_ftsPrefixed1240); + ftsTest21=ftsTest(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsTest.add(ftsTest21.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:415:30: ( boost )? + int alt10=2; + int LA10_0 = input.LA(1); + if ( (LA10_0==CARAT) ) { + alt10=1; + } + switch (alt10) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:415:30: boost + { + pushFollow(FOLLOW_boost_in_ftsPrefixed1242); + boost22=boost(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_boost.add(boost22.getTree()); + } + break; + + } + + // AST REWRITE + // elements: boost, ftsTest + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 416:17: -> ^( NEGATION ftsTest ( boost )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:417:25: ^( NEGATION ftsTest ( boost )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(NEGATION, "NEGATION"), root_1); + adaptor.addChild(root_1, stream_ftsTest.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:417:44: ( boost )? + if ( stream_boost.hasNext() ) { + adaptor.addChild(root_1, stream_boost.nextTree()); + } + stream_boost.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:418:11: ftsTest ( boost )? + { + pushFollow(FOLLOW_ftsTest_in_ftsPrefixed1306); + ftsTest23=ftsTest(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsTest.add(ftsTest23.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:418:19: ( boost )? + int alt11=2; + int LA11_0 = input.LA(1); + if ( (LA11_0==CARAT) ) { + alt11=1; + } + switch (alt11) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:418:19: boost + { + pushFollow(FOLLOW_boost_in_ftsPrefixed1308); + boost24=boost(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_boost.add(boost24.getTree()); + } + break; + + } + + // AST REWRITE + // elements: boost, ftsTest + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 419:17: -> ^( DEFAULT ftsTest ( boost )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:420:25: ^( DEFAULT ftsTest ( boost )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(DEFAULT, "DEFAULT"), root_1); + adaptor.addChild(root_1, stream_ftsTest.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:420:43: ( boost )? + if ( stream_boost.hasNext() ) { + adaptor.addChild(root_1, stream_boost.nextTree()); + } + stream_boost.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:421:11: PLUS ftsTest ( boost )? + { + PLUS25=(Token)match(input,PLUS,FOLLOW_PLUS_in_ftsPrefixed1372); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_PLUS.add(PLUS25); + + pushFollow(FOLLOW_ftsTest_in_ftsPrefixed1374); + ftsTest26=ftsTest(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsTest.add(ftsTest26.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:421:24: ( boost )? + int alt12=2; + int LA12_0 = input.LA(1); + if ( (LA12_0==CARAT) ) { + alt12=1; + } + switch (alt12) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:421:24: boost + { + pushFollow(FOLLOW_boost_in_ftsPrefixed1376); + boost27=boost(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_boost.add(boost27.getTree()); + } + break; + + } + + // AST REWRITE + // elements: ftsTest, boost + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 422:17: -> ^( MANDATORY ftsTest ( boost )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:423:25: ^( MANDATORY ftsTest ( boost )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(MANDATORY, "MANDATORY"), root_1); + adaptor.addChild(root_1, stream_ftsTest.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:423:45: ( boost )? + if ( stream_boost.hasNext() ) { + adaptor.addChild(root_1, stream_boost.nextTree()); + } + stream_boost.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:424:11: BAR ftsTest ( boost )? + { + BAR28=(Token)match(input,BAR,FOLLOW_BAR_in_ftsPrefixed1440); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_BAR.add(BAR28); + + pushFollow(FOLLOW_ftsTest_in_ftsPrefixed1442); + ftsTest29=ftsTest(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsTest.add(ftsTest29.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:424:23: ( boost )? + int alt13=2; + int LA13_0 = input.LA(1); + if ( (LA13_0==CARAT) ) { + alt13=1; + } + switch (alt13) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:424:23: boost + { + pushFollow(FOLLOW_boost_in_ftsPrefixed1444); + boost30=boost(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_boost.add(boost30.getTree()); + } + break; + + } + + // AST REWRITE + // elements: boost, ftsTest + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 425:17: -> ^( OPTIONAL ftsTest ( boost )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:426:25: ^( OPTIONAL ftsTest ( boost )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(OPTIONAL, "OPTIONAL"), root_1); + adaptor.addChild(root_1, stream_ftsTest.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:426:44: ( boost )? + if ( stream_boost.hasNext() ) { + adaptor.addChild(root_1, stream_boost.nextTree()); + } + stream_boost.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:427:11: MINUS ftsTest ( boost )? + { + MINUS31=(Token)match(input,MINUS,FOLLOW_MINUS_in_ftsPrefixed1508); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_MINUS.add(MINUS31); + + pushFollow(FOLLOW_ftsTest_in_ftsPrefixed1510); + ftsTest32=ftsTest(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsTest.add(ftsTest32.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:427:25: ( boost )? + int alt14=2; + int LA14_0 = input.LA(1); + if ( (LA14_0==CARAT) ) { + alt14=1; + } + switch (alt14) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:427:25: boost + { + pushFollow(FOLLOW_boost_in_ftsPrefixed1512); + boost33=boost(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_boost.add(boost33.getTree()); + } + break; + + } + + // AST REWRITE + // elements: ftsTest, boost + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 428:17: -> ^( EXCLUDE ftsTest ( boost )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:429:25: ^( EXCLUDE ftsTest ( boost )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(EXCLUDE, "EXCLUDE"), root_1); + adaptor.addChild(root_1, stream_ftsTest.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:429:43: ( boost )? + if ( stream_boost.hasNext() ) { + adaptor.addChild(root_1, stream_boost.nextTree()); + } + stream_boost.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsPrefixed" + + + public static class cmisPrefixed_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "cmisPrefixed" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:432:1: cmisPrefixed : ( cmisTest -> ^( DEFAULT cmisTest ) | MINUS cmisTest -> ^( EXCLUDE cmisTest ) ); + public final FTSParser.cmisPrefixed_return cmisPrefixed() throws RecognitionException { + FTSParser.cmisPrefixed_return retval = new FTSParser.cmisPrefixed_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token MINUS35=null; + ParserRuleReturnScope cmisTest34 =null; + ParserRuleReturnScope cmisTest36 =null; + + Object MINUS35_tree=null; + RewriteRuleTokenStream stream_MINUS=new RewriteRuleTokenStream(adaptor,"token MINUS"); + RewriteRuleSubtreeStream stream_cmisTest=new RewriteRuleSubtreeStream(adaptor,"rule cmisTest"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:433:9: ( cmisTest -> ^( DEFAULT cmisTest ) | MINUS cmisTest -> ^( EXCLUDE cmisTest ) ) + int alt16=2; + int LA16_0 = input.LA(1); + if ( (LA16_0==COMMA||LA16_0==DATETIME||LA16_0==DECIMAL_INTEGER_LITERAL||LA16_0==DOT||LA16_0==FLOATING_POINT_LITERAL||(LA16_0 >= FTSPHRASE && LA16_0 <= FTSWORD)||LA16_0==ID||LA16_0==NOT||LA16_0==QUESTION_MARK||LA16_0==STAR||LA16_0==TO||LA16_0==URI) ) { + alt16=1; + } + else if ( (LA16_0==MINUS) ) { + alt16=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 16, 0, input); + throw nvae; + } + + switch (alt16) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:434:9: cmisTest + { + pushFollow(FOLLOW_cmisTest_in_cmisPrefixed1597); + cmisTest34=cmisTest(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_cmisTest.add(cmisTest34.getTree()); + // AST REWRITE + // elements: cmisTest + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 435:17: -> ^( DEFAULT cmisTest ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:436:25: ^( DEFAULT cmisTest ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(DEFAULT, "DEFAULT"), root_1); + adaptor.addChild(root_1, stream_cmisTest.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:437:11: MINUS cmisTest + { + MINUS35=(Token)match(input,MINUS,FOLLOW_MINUS_in_cmisPrefixed1657); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_MINUS.add(MINUS35); + + pushFollow(FOLLOW_cmisTest_in_cmisPrefixed1659); + cmisTest36=cmisTest(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_cmisTest.add(cmisTest36.getTree()); + // AST REWRITE + // elements: cmisTest + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 438:17: -> ^( EXCLUDE cmisTest ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:439:25: ^( EXCLUDE cmisTest ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(EXCLUDE, "EXCLUDE"), root_1); + adaptor.addChild(root_1, stream_cmisTest.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "cmisPrefixed" + + + public static class ftsTest_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsTest" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:445:1: ftsTest : ( ( ftsFieldGroupProximity )=> ftsFieldGroupProximity -> ^( PROXIMITY ftsFieldGroupProximity ) | ( ftsRange )=> ftsRange -> ^( RANGE ftsRange ) | ( ftsFieldGroup )=> ftsFieldGroup -> ftsFieldGroup | ( ftsTermOrPhrase )=> ftsTermOrPhrase | ( ftsExactTermOrPhrase )=> ftsExactTermOrPhrase | ( ftsTokenisedTermOrPhrase )=> ftsTokenisedTermOrPhrase | LPAREN ftsDisjunction RPAREN -> ftsDisjunction | template -> template ); + public final FTSParser.ftsTest_return ftsTest() throws RecognitionException { + FTSParser.ftsTest_return retval = new FTSParser.ftsTest_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token LPAREN43=null; + Token RPAREN45=null; + ParserRuleReturnScope ftsFieldGroupProximity37 =null; + ParserRuleReturnScope ftsRange38 =null; + ParserRuleReturnScope ftsFieldGroup39 =null; + ParserRuleReturnScope ftsTermOrPhrase40 =null; + ParserRuleReturnScope ftsExactTermOrPhrase41 =null; + ParserRuleReturnScope ftsTokenisedTermOrPhrase42 =null; + ParserRuleReturnScope ftsDisjunction44 =null; + ParserRuleReturnScope template46 =null; + + Object LPAREN43_tree=null; + Object RPAREN45_tree=null; + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleSubtreeStream stream_template=new RewriteRuleSubtreeStream(adaptor,"rule template"); + RewriteRuleSubtreeStream stream_ftsRange=new RewriteRuleSubtreeStream(adaptor,"rule ftsRange"); + RewriteRuleSubtreeStream stream_ftsFieldGroupProximity=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupProximity"); + RewriteRuleSubtreeStream stream_ftsDisjunction=new RewriteRuleSubtreeStream(adaptor,"rule ftsDisjunction"); + RewriteRuleSubtreeStream stream_ftsFieldGroup=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroup"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:446:9: ( ( ftsFieldGroupProximity )=> ftsFieldGroupProximity -> ^( PROXIMITY ftsFieldGroupProximity ) | ( ftsRange )=> ftsRange -> ^( RANGE ftsRange ) | ( ftsFieldGroup )=> ftsFieldGroup -> ftsFieldGroup | ( ftsTermOrPhrase )=> ftsTermOrPhrase | ( ftsExactTermOrPhrase )=> ftsExactTermOrPhrase | ( ftsTokenisedTermOrPhrase )=> ftsTokenisedTermOrPhrase | LPAREN ftsDisjunction RPAREN -> ftsDisjunction | template -> template ) + int alt17=8; + alt17 = dfa17.predict(input); + switch (alt17) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:447:12: ( ftsFieldGroupProximity )=> ftsFieldGroupProximity + { + pushFollow(FOLLOW_ftsFieldGroupProximity_in_ftsTest1751); + ftsFieldGroupProximity37=ftsFieldGroupProximity(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupProximity.add(ftsFieldGroupProximity37.getTree()); + // AST REWRITE + // elements: ftsFieldGroupProximity + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 448:17: -> ^( PROXIMITY ftsFieldGroupProximity ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:449:25: ^( PROXIMITY ftsFieldGroupProximity ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PROXIMITY, "PROXIMITY"), root_1); + adaptor.addChild(root_1, stream_ftsFieldGroupProximity.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:451:12: ( ftsRange )=> ftsRange + { + pushFollow(FOLLOW_ftsRange_in_ftsTest1828); + ftsRange38=ftsRange(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsRange.add(ftsRange38.getTree()); + // AST REWRITE + // elements: ftsRange + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 452:17: -> ^( RANGE ftsRange ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:453:25: ^( RANGE ftsRange ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(RANGE, "RANGE"), root_1); + adaptor.addChild(root_1, stream_ftsRange.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:455:12: ( ftsFieldGroup )=> ftsFieldGroup + { + pushFollow(FOLLOW_ftsFieldGroup_in_ftsTest1907); + ftsFieldGroup39=ftsFieldGroup(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroup.add(ftsFieldGroup39.getTree()); + // AST REWRITE + // elements: ftsFieldGroup + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 456:17: -> ftsFieldGroup + { + adaptor.addChild(root_0, stream_ftsFieldGroup.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:458:12: ( ftsTermOrPhrase )=> ftsTermOrPhrase + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_ftsTermOrPhrase_in_ftsTest1956); + ftsTermOrPhrase40=ftsTermOrPhrase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsTermOrPhrase40.getTree()); + + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:460:12: ( ftsExactTermOrPhrase )=> ftsExactTermOrPhrase + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_ftsExactTermOrPhrase_in_ftsTest1985); + ftsExactTermOrPhrase41=ftsExactTermOrPhrase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsExactTermOrPhrase41.getTree()); + + } + break; + case 6 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:462:12: ( ftsTokenisedTermOrPhrase )=> ftsTokenisedTermOrPhrase + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_ftsTokenisedTermOrPhrase_in_ftsTest2015); + ftsTokenisedTermOrPhrase42=ftsTokenisedTermOrPhrase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsTokenisedTermOrPhrase42.getTree()); + + } + break; + case 7 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:465:12: LPAREN ftsDisjunction RPAREN + { + LPAREN43=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_ftsTest2046); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(LPAREN43); + + pushFollow(FOLLOW_ftsDisjunction_in_ftsTest2048); + ftsDisjunction44=ftsDisjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsDisjunction.add(ftsDisjunction44.getTree()); + RPAREN45=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_ftsTest2050); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(RPAREN45); + + // AST REWRITE + // elements: ftsDisjunction + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 466:17: -> ftsDisjunction + { + adaptor.addChild(root_0, stream_ftsDisjunction.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + case 8 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:467:12: template + { + pushFollow(FOLLOW_template_in_ftsTest2083); + template46=template(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_template.add(template46.getTree()); + // AST REWRITE + // elements: template + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 468:17: -> template + { + adaptor.addChild(root_0, stream_template.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsTest" + + + public static class cmisTest_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "cmisTest" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:471:1: cmisTest : ( cmisTerm -> ^( TERM cmisTerm ) | cmisPhrase -> ^( PHRASE cmisPhrase ) ); + public final FTSParser.cmisTest_return cmisTest() throws RecognitionException { + FTSParser.cmisTest_return retval = new FTSParser.cmisTest_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope cmisTerm47 =null; + ParserRuleReturnScope cmisPhrase48 =null; + + RewriteRuleSubtreeStream stream_cmisTerm=new RewriteRuleSubtreeStream(adaptor,"rule cmisTerm"); + RewriteRuleSubtreeStream stream_cmisPhrase=new RewriteRuleSubtreeStream(adaptor,"rule cmisPhrase"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:472:9: ( cmisTerm -> ^( TERM cmisTerm ) | cmisPhrase -> ^( PHRASE cmisPhrase ) ) + int alt18=2; + int LA18_0 = input.LA(1); + if ( (LA18_0==COMMA||LA18_0==DATETIME||LA18_0==DECIMAL_INTEGER_LITERAL||LA18_0==DOT||LA18_0==FLOATING_POINT_LITERAL||(LA18_0 >= FTSPRE && LA18_0 <= FTSWORD)||LA18_0==ID||LA18_0==NOT||LA18_0==QUESTION_MARK||LA18_0==STAR||LA18_0==TO||LA18_0==URI) ) { + alt18=1; + } + else if ( (LA18_0==FTSPHRASE) ) { + alt18=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 18, 0, input); + throw nvae; + } + + switch (alt18) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:473:9: cmisTerm + { + pushFollow(FOLLOW_cmisTerm_in_cmisTest2136); + cmisTerm47=cmisTerm(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_cmisTerm.add(cmisTerm47.getTree()); + // AST REWRITE + // elements: cmisTerm + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 474:17: -> ^( TERM cmisTerm ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:475:25: ^( TERM cmisTerm ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(TERM, "TERM"), root_1); + adaptor.addChild(root_1, stream_cmisTerm.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:476:11: cmisPhrase + { + pushFollow(FOLLOW_cmisPhrase_in_cmisTest2196); + cmisPhrase48=cmisPhrase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_cmisPhrase.add(cmisPhrase48.getTree()); + // AST REWRITE + // elements: cmisPhrase + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 477:17: -> ^( PHRASE cmisPhrase ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:478:25: ^( PHRASE cmisPhrase ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PHRASE, "PHRASE"), root_1); + adaptor.addChild(root_1, stream_cmisPhrase.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "cmisTest" + + + public static class template_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "template" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:481:1: template : ( PERCENT tempReference -> ^( TEMPLATE tempReference ) | PERCENT LPAREN ( tempReference ( COMMA )? )+ RPAREN -> ^( TEMPLATE ( tempReference )+ ) ); + public final FTSParser.template_return template() throws RecognitionException { + FTSParser.template_return retval = new FTSParser.template_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token PERCENT49=null; + Token PERCENT51=null; + Token LPAREN52=null; + Token COMMA54=null; + Token RPAREN55=null; + ParserRuleReturnScope tempReference50 =null; + ParserRuleReturnScope tempReference53 =null; + + Object PERCENT49_tree=null; + Object PERCENT51_tree=null; + Object LPAREN52_tree=null; + Object COMMA54_tree=null; + Object RPAREN55_tree=null; + RewriteRuleTokenStream stream_COMMA=new RewriteRuleTokenStream(adaptor,"token COMMA"); + RewriteRuleTokenStream stream_PERCENT=new RewriteRuleTokenStream(adaptor,"token PERCENT"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleSubtreeStream stream_tempReference=new RewriteRuleSubtreeStream(adaptor,"rule tempReference"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:482:9: ( PERCENT tempReference -> ^( TEMPLATE tempReference ) | PERCENT LPAREN ( tempReference ( COMMA )? )+ RPAREN -> ^( TEMPLATE ( tempReference )+ ) ) + int alt21=2; + int LA21_0 = input.LA(1); + if ( (LA21_0==PERCENT) ) { + int LA21_1 = input.LA(2); + if ( (LA21_1==LPAREN) ) { + alt21=2; + } + else if ( ((LA21_1 >= AND && LA21_1 <= AT)||LA21_1==ID||LA21_1==NOT||LA21_1==OR||LA21_1==TO||LA21_1==URI) ) { + alt21=1; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 21, 1, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 21, 0, input); + throw nvae; + } + + switch (alt21) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:483:9: PERCENT tempReference + { + PERCENT49=(Token)match(input,PERCENT,FOLLOW_PERCENT_in_template2277); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_PERCENT.add(PERCENT49); + + pushFollow(FOLLOW_tempReference_in_template2279); + tempReference50=tempReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_tempReference.add(tempReference50.getTree()); + // AST REWRITE + // elements: tempReference + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 484:17: -> ^( TEMPLATE tempReference ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:485:25: ^( TEMPLATE tempReference ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(TEMPLATE, "TEMPLATE"), root_1); + adaptor.addChild(root_1, stream_tempReference.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:486:11: PERCENT LPAREN ( tempReference ( COMMA )? )+ RPAREN + { + PERCENT51=(Token)match(input,PERCENT,FOLLOW_PERCENT_in_template2339); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_PERCENT.add(PERCENT51); + + LPAREN52=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_template2341); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(LPAREN52); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:486:26: ( tempReference ( COMMA )? )+ + int cnt20=0; + loop20: + while (true) { + int alt20=2; + int LA20_0 = input.LA(1); + if ( ((LA20_0 >= AND && LA20_0 <= AT)||LA20_0==ID||LA20_0==NOT||LA20_0==OR||LA20_0==TO||LA20_0==URI) ) { + alt20=1; + } + + switch (alt20) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:486:27: tempReference ( COMMA )? + { + pushFollow(FOLLOW_tempReference_in_template2344); + tempReference53=tempReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_tempReference.add(tempReference53.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:486:41: ( COMMA )? + int alt19=2; + int LA19_0 = input.LA(1); + if ( (LA19_0==COMMA) ) { + alt19=1; + } + switch (alt19) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:486:41: COMMA + { + COMMA54=(Token)match(input,COMMA,FOLLOW_COMMA_in_template2346); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_COMMA.add(COMMA54); + + } + break; + + } + + } + break; + + default : + if ( cnt20 >= 1 ) break loop20; + if (state.backtracking>0) {state.failed=true; return retval;} + EarlyExitException eee = new EarlyExitException(20, input); + throw eee; + } + cnt20++; + } + + RPAREN55=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_template2351); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(RPAREN55); + + // AST REWRITE + // elements: tempReference + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 487:17: -> ^( TEMPLATE ( tempReference )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:488:25: ^( TEMPLATE ( tempReference )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(TEMPLATE, "TEMPLATE"), root_1); + if ( !(stream_tempReference.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_tempReference.hasNext() ) { + adaptor.addChild(root_1, stream_tempReference.nextTree()); + } + stream_tempReference.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "template" + + + public static class fuzzy_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "fuzzy" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:491:1: fuzzy : TILDA number -> ^( FUZZY number ) ; + public final FTSParser.fuzzy_return fuzzy() throws RecognitionException { + FTSParser.fuzzy_return retval = new FTSParser.fuzzy_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token TILDA56=null; + ParserRuleReturnScope number57 =null; + + Object TILDA56_tree=null; + RewriteRuleTokenStream stream_TILDA=new RewriteRuleTokenStream(adaptor,"token TILDA"); + RewriteRuleSubtreeStream stream_number=new RewriteRuleSubtreeStream(adaptor,"rule number"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:492:9: ( TILDA number -> ^( FUZZY number ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:493:9: TILDA number + { + TILDA56=(Token)match(input,TILDA,FOLLOW_TILDA_in_fuzzy2433); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_TILDA.add(TILDA56); + + pushFollow(FOLLOW_number_in_fuzzy2435); + number57=number(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_number.add(number57.getTree()); + // AST REWRITE + // elements: number + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 494:17: -> ^( FUZZY number ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:495:25: ^( FUZZY number ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FUZZY, "FUZZY"), root_1); + adaptor.addChild(root_1, stream_number.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "fuzzy" + + + public static class slop_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "slop" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:498:1: slop : TILDA DECIMAL_INTEGER_LITERAL -> ^( FUZZY DECIMAL_INTEGER_LITERAL ) ; + public final FTSParser.slop_return slop() throws RecognitionException { + FTSParser.slop_return retval = new FTSParser.slop_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token TILDA58=null; + Token DECIMAL_INTEGER_LITERAL59=null; + + Object TILDA58_tree=null; + Object DECIMAL_INTEGER_LITERAL59_tree=null; + RewriteRuleTokenStream stream_DECIMAL_INTEGER_LITERAL=new RewriteRuleTokenStream(adaptor,"token DECIMAL_INTEGER_LITERAL"); + RewriteRuleTokenStream stream_TILDA=new RewriteRuleTokenStream(adaptor,"token TILDA"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:499:9: ( TILDA DECIMAL_INTEGER_LITERAL -> ^( FUZZY DECIMAL_INTEGER_LITERAL ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:500:9: TILDA DECIMAL_INTEGER_LITERAL + { + TILDA58=(Token)match(input,TILDA,FOLLOW_TILDA_in_slop2516); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_TILDA.add(TILDA58); + + DECIMAL_INTEGER_LITERAL59=(Token)match(input,DECIMAL_INTEGER_LITERAL,FOLLOW_DECIMAL_INTEGER_LITERAL_in_slop2518); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DECIMAL_INTEGER_LITERAL.add(DECIMAL_INTEGER_LITERAL59); + + // AST REWRITE + // elements: DECIMAL_INTEGER_LITERAL + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 501:17: -> ^( FUZZY DECIMAL_INTEGER_LITERAL ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:502:25: ^( FUZZY DECIMAL_INTEGER_LITERAL ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FUZZY, "FUZZY"), root_1); + adaptor.addChild(root_1, stream_DECIMAL_INTEGER_LITERAL.nextNode()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "slop" + + + public static class boost_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "boost" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:505:1: boost : CARAT number -> ^( BOOST number ) ; + public final FTSParser.boost_return boost() throws RecognitionException { + FTSParser.boost_return retval = new FTSParser.boost_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token CARAT60=null; + ParserRuleReturnScope number61 =null; + + Object CARAT60_tree=null; + RewriteRuleTokenStream stream_CARAT=new RewriteRuleTokenStream(adaptor,"token CARAT"); + RewriteRuleSubtreeStream stream_number=new RewriteRuleSubtreeStream(adaptor,"rule number"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:506:9: ( CARAT number -> ^( BOOST number ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:507:9: CARAT number + { + CARAT60=(Token)match(input,CARAT,FOLLOW_CARAT_in_boost2599); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_CARAT.add(CARAT60); + + pushFollow(FOLLOW_number_in_boost2601); + number61=number(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_number.add(number61.getTree()); + // AST REWRITE + // elements: number + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 508:17: -> ^( BOOST number ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:509:25: ^( BOOST number ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(BOOST, "BOOST"), root_1); + adaptor.addChild(root_1, stream_number.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "boost" + + + public static class ftsTermOrPhrase_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsTermOrPhrase" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:512:1: ftsTermOrPhrase : ( ( fieldReference COLON )=> fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord fieldReference ( fuzzy )? ) ) | FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord ( fuzzy )? ) ); + public final FTSParser.ftsTermOrPhrase_return ftsTermOrPhrase() throws RecognitionException { + FTSParser.ftsTermOrPhrase_return retval = new FTSParser.ftsTermOrPhrase_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token COLON63=null; + Token FTSPHRASE64=null; + Token FTSPHRASE68=null; + ParserRuleReturnScope fieldReference62 =null; + ParserRuleReturnScope slop65 =null; + ParserRuleReturnScope ftsWord66 =null; + ParserRuleReturnScope fuzzy67 =null; + ParserRuleReturnScope slop69 =null; + ParserRuleReturnScope ftsWord70 =null; + ParserRuleReturnScope fuzzy71 =null; + + Object COLON63_tree=null; + Object FTSPHRASE64_tree=null; + Object FTSPHRASE68_tree=null; + RewriteRuleTokenStream stream_FTSPHRASE=new RewriteRuleTokenStream(adaptor,"token FTSPHRASE"); + RewriteRuleTokenStream stream_COLON=new RewriteRuleTokenStream(adaptor,"token COLON"); + RewriteRuleSubtreeStream stream_ftsWord=new RewriteRuleSubtreeStream(adaptor,"rule ftsWord"); + RewriteRuleSubtreeStream stream_fieldReference=new RewriteRuleSubtreeStream(adaptor,"rule fieldReference"); + RewriteRuleSubtreeStream stream_fuzzy=new RewriteRuleSubtreeStream(adaptor,"rule fuzzy"); + RewriteRuleSubtreeStream stream_slop=new RewriteRuleSubtreeStream(adaptor,"rule slop"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:513:9: ( ( fieldReference COLON )=> fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord fieldReference ( fuzzy )? ) ) | FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord ( fuzzy )? ) ) + int alt27=3; + int LA27_0 = input.LA(1); + if ( (LA27_0==AT) && (synpred8_FTS())) { + alt27=1; + } + else if ( (LA27_0==ID) ) { + int LA27_2 = input.LA(2); + if ( (LA27_2==DOT) ) { + int LA27_10 = input.LA(3); + if ( (LA27_10==ID) ) { + int LA27_17 = input.LA(4); + if ( (synpred8_FTS()) ) { + alt27=1; + } + else if ( (true) ) { + alt27=3; + } + + } + else if ( (LA27_10==EOF||(LA27_10 >= AMP && LA27_10 <= BAR)||LA27_10==CARAT||LA27_10==COMMA||LA27_10==DATETIME||LA27_10==DECIMAL_INTEGER_LITERAL||LA27_10==DOT||LA27_10==EQUALS||LA27_10==EXCLAMATION||LA27_10==FLOATING_POINT_LITERAL||(LA27_10 >= FTSPHRASE && LA27_10 <= FTSWORD)||(LA27_10 >= LPAREN && LA27_10 <= LT)||LA27_10==MINUS||LA27_10==NOT||(LA27_10 >= OR && LA27_10 <= PERCENT)||LA27_10==PLUS||LA27_10==QUESTION_MARK||LA27_10==RPAREN||LA27_10==STAR||(LA27_10 >= TILDA && LA27_10 <= TO)||LA27_10==URI) ) { + alt27=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 3 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 27, 10, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + else if ( (LA27_2==COLON) && (synpred8_FTS())) { + alt27=1; + } + else if ( (LA27_2==EOF||(LA27_2 >= AMP && LA27_2 <= BAR)||LA27_2==CARAT||LA27_2==COMMA||LA27_2==DATETIME||LA27_2==DECIMAL_INTEGER_LITERAL||LA27_2==EQUALS||LA27_2==EXCLAMATION||LA27_2==FLOATING_POINT_LITERAL||(LA27_2 >= FTSPHRASE && LA27_2 <= FTSWORD)||LA27_2==ID||(LA27_2 >= LPAREN && LA27_2 <= LT)||LA27_2==MINUS||LA27_2==NOT||(LA27_2 >= OR && LA27_2 <= PERCENT)||LA27_2==PLUS||LA27_2==QUESTION_MARK||LA27_2==RPAREN||LA27_2==STAR||(LA27_2 >= TILDA && LA27_2 <= TO)||LA27_2==URI) ) { + alt27=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 27, 2, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + else if ( (LA27_0==TO) ) { + int LA27_3 = input.LA(2); + if ( (LA27_3==COLON) && (synpred8_FTS())) { + alt27=1; + } + else if ( (LA27_3==EOF||(LA27_3 >= AMP && LA27_3 <= BAR)||LA27_3==CARAT||LA27_3==COMMA||LA27_3==DATETIME||LA27_3==DECIMAL_INTEGER_LITERAL||LA27_3==DOT||LA27_3==EQUALS||LA27_3==EXCLAMATION||LA27_3==FLOATING_POINT_LITERAL||(LA27_3 >= FTSPHRASE && LA27_3 <= FTSWORD)||LA27_3==ID||(LA27_3 >= LPAREN && LA27_3 <= LT)||LA27_3==MINUS||LA27_3==NOT||(LA27_3 >= OR && LA27_3 <= PERCENT)||LA27_3==PLUS||LA27_3==QUESTION_MARK||LA27_3==RPAREN||LA27_3==STAR||(LA27_3 >= TILDA && LA27_3 <= TO)||LA27_3==URI) ) { + alt27=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 27, 3, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + else if ( (LA27_0==OR) && (synpred8_FTS())) { + alt27=1; + } + else if ( (LA27_0==AND) && (synpred8_FTS())) { + alt27=1; + } + else if ( (LA27_0==NOT) ) { + int LA27_6 = input.LA(2); + if ( (LA27_6==COLON) && (synpred8_FTS())) { + alt27=1; + } + else if ( (LA27_6==EOF||(LA27_6 >= AMP && LA27_6 <= BAR)||LA27_6==CARAT||LA27_6==COMMA||LA27_6==DATETIME||LA27_6==DECIMAL_INTEGER_LITERAL||LA27_6==DOT||LA27_6==EQUALS||LA27_6==EXCLAMATION||LA27_6==FLOATING_POINT_LITERAL||(LA27_6 >= FTSPHRASE && LA27_6 <= FTSWORD)||LA27_6==ID||(LA27_6 >= LPAREN && LA27_6 <= LT)||LA27_6==MINUS||LA27_6==NOT||(LA27_6 >= OR && LA27_6 <= PERCENT)||LA27_6==PLUS||LA27_6==QUESTION_MARK||LA27_6==RPAREN||LA27_6==STAR||(LA27_6 >= TILDA && LA27_6 <= TO)||LA27_6==URI) ) { + alt27=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 27, 6, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + else if ( (LA27_0==URI) ) { + switch ( input.LA(2) ) { + case ID: + { + int LA27_12 = input.LA(3); + if ( (LA27_12==DOT) ) { + int LA27_18 = input.LA(4); + if ( (LA27_18==ID) ) { + int LA27_20 = input.LA(5); + if ( (synpred8_FTS()) ) { + alt27=1; + } + else if ( (true) ) { + alt27=3; + } + + } + else if ( (LA27_18==EOF||(LA27_18 >= AMP && LA27_18 <= BAR)||LA27_18==CARAT||LA27_18==COMMA||LA27_18==DATETIME||LA27_18==DECIMAL_INTEGER_LITERAL||LA27_18==DOT||LA27_18==EQUALS||LA27_18==EXCLAMATION||LA27_18==FLOATING_POINT_LITERAL||(LA27_18 >= FTSPHRASE && LA27_18 <= FTSWORD)||(LA27_18 >= LPAREN && LA27_18 <= LT)||LA27_18==MINUS||LA27_18==NOT||(LA27_18 >= OR && LA27_18 <= PERCENT)||LA27_18==PLUS||LA27_18==QUESTION_MARK||LA27_18==RPAREN||LA27_18==STAR||(LA27_18 >= TILDA && LA27_18 <= TO)||LA27_18==URI) ) { + alt27=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 4 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 27, 18, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + else if ( (LA27_12==COLON) && (synpred8_FTS())) { + alt27=1; + } + else if ( (LA27_12==EOF||(LA27_12 >= AMP && LA27_12 <= BAR)||LA27_12==CARAT||LA27_12==COMMA||LA27_12==DATETIME||LA27_12==DECIMAL_INTEGER_LITERAL||LA27_12==EQUALS||LA27_12==EXCLAMATION||LA27_12==FLOATING_POINT_LITERAL||(LA27_12 >= FTSPHRASE && LA27_12 <= FTSWORD)||LA27_12==ID||(LA27_12 >= LPAREN && LA27_12 <= LT)||LA27_12==MINUS||LA27_12==NOT||(LA27_12 >= OR && LA27_12 <= PERCENT)||LA27_12==PLUS||LA27_12==QUESTION_MARK||LA27_12==RPAREN||LA27_12==STAR||(LA27_12 >= TILDA && LA27_12 <= TO)||LA27_12==URI) ) { + alt27=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 3 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 27, 12, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case TO: + { + int LA27_13 = input.LA(3); + if ( (LA27_13==COLON) && (synpred8_FTS())) { + alt27=1; + } + else if ( (LA27_13==EOF||(LA27_13 >= AMP && LA27_13 <= BAR)||LA27_13==CARAT||LA27_13==COMMA||LA27_13==DATETIME||LA27_13==DECIMAL_INTEGER_LITERAL||LA27_13==DOT||LA27_13==EQUALS||LA27_13==EXCLAMATION||LA27_13==FLOATING_POINT_LITERAL||(LA27_13 >= FTSPHRASE && LA27_13 <= FTSWORD)||LA27_13==ID||(LA27_13 >= LPAREN && LA27_13 <= LT)||LA27_13==MINUS||LA27_13==NOT||(LA27_13 >= OR && LA27_13 <= PERCENT)||LA27_13==PLUS||LA27_13==QUESTION_MARK||LA27_13==RPAREN||LA27_13==STAR||(LA27_13 >= TILDA && LA27_13 <= TO)||LA27_13==URI) ) { + alt27=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 3 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 27, 13, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case OR: + { + int LA27_14 = input.LA(3); + if ( (LA27_14==COLON) && (synpred8_FTS())) { + alt27=1; + } + else if ( (LA27_14==EOF||(LA27_14 >= AMP && LA27_14 <= BAR)||LA27_14==CARAT||LA27_14==COMMA||LA27_14==DATETIME||LA27_14==DECIMAL_INTEGER_LITERAL||LA27_14==DOT||LA27_14==EQUALS||LA27_14==EXCLAMATION||LA27_14==FLOATING_POINT_LITERAL||(LA27_14 >= FTSPHRASE && LA27_14 <= FTSWORD)||LA27_14==ID||(LA27_14 >= LPAREN && LA27_14 <= LT)||LA27_14==MINUS||LA27_14==NOT||(LA27_14 >= OR && LA27_14 <= PERCENT)||LA27_14==PLUS||LA27_14==QUESTION_MARK||LA27_14==RPAREN||LA27_14==STAR||(LA27_14 >= TILDA && LA27_14 <= TO)||LA27_14==URI) ) { + alt27=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 3 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 27, 14, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case AND: + { + int LA27_15 = input.LA(3); + if ( (LA27_15==COLON) && (synpred8_FTS())) { + alt27=1; + } + else if ( (LA27_15==EOF||(LA27_15 >= AMP && LA27_15 <= BAR)||LA27_15==CARAT||LA27_15==COMMA||LA27_15==DATETIME||LA27_15==DECIMAL_INTEGER_LITERAL||LA27_15==DOT||LA27_15==EQUALS||LA27_15==EXCLAMATION||LA27_15==FLOATING_POINT_LITERAL||(LA27_15 >= FTSPHRASE && LA27_15 <= FTSWORD)||LA27_15==ID||(LA27_15 >= LPAREN && LA27_15 <= LT)||LA27_15==MINUS||LA27_15==NOT||(LA27_15 >= OR && LA27_15 <= PERCENT)||LA27_15==PLUS||LA27_15==QUESTION_MARK||LA27_15==RPAREN||LA27_15==STAR||(LA27_15 >= TILDA && LA27_15 <= TO)||LA27_15==URI) ) { + alt27=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 3 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 27, 15, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case NOT: + { + int LA27_16 = input.LA(3); + if ( (LA27_16==COLON) && (synpred8_FTS())) { + alt27=1; + } + else if ( (LA27_16==EOF||(LA27_16 >= AMP && LA27_16 <= BAR)||LA27_16==CARAT||LA27_16==COMMA||LA27_16==DATETIME||LA27_16==DECIMAL_INTEGER_LITERAL||LA27_16==DOT||LA27_16==EQUALS||LA27_16==EXCLAMATION||LA27_16==FLOATING_POINT_LITERAL||(LA27_16 >= FTSPHRASE && LA27_16 <= FTSWORD)||LA27_16==ID||(LA27_16 >= LPAREN && LA27_16 <= LT)||LA27_16==MINUS||LA27_16==NOT||(LA27_16 >= OR && LA27_16 <= PERCENT)||LA27_16==PLUS||LA27_16==QUESTION_MARK||LA27_16==RPAREN||LA27_16==STAR||(LA27_16 >= TILDA && LA27_16 <= TO)||LA27_16==URI) ) { + alt27=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 3 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 27, 16, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 27, 7, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + } + else if ( (LA27_0==FTSPHRASE) ) { + alt27=2; + } + else if ( (LA27_0==COMMA||LA27_0==DATETIME||LA27_0==DECIMAL_INTEGER_LITERAL||LA27_0==DOT||LA27_0==FLOATING_POINT_LITERAL||(LA27_0 >= FTSPRE && LA27_0 <= FTSWORD)||LA27_0==QUESTION_MARK||LA27_0==STAR) ) { + alt27=3; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 27, 0, input); + throw nvae; + } + + switch (alt27) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:514:9: ( fieldReference COLON )=> fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord fieldReference ( fuzzy )? ) ) + { + pushFollow(FOLLOW_fieldReference_in_ftsTermOrPhrase2690); + fieldReference62=fieldReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fieldReference.add(fieldReference62.getTree()); + COLON63=(Token)match(input,COLON,FOLLOW_COLON_in_ftsTermOrPhrase2692); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_COLON.add(COLON63); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:515:9: ( FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord fieldReference ( fuzzy )? ) ) + int alt24=2; + int LA24_0 = input.LA(1); + if ( (LA24_0==FTSPHRASE) ) { + alt24=1; + } + else if ( (LA24_0==COMMA||LA24_0==DATETIME||LA24_0==DECIMAL_INTEGER_LITERAL||LA24_0==DOT||LA24_0==FLOATING_POINT_LITERAL||(LA24_0 >= FTSPRE && LA24_0 <= FTSWORD)||LA24_0==ID||LA24_0==NOT||LA24_0==QUESTION_MARK||LA24_0==STAR||LA24_0==TO||LA24_0==URI) ) { + alt24=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 24, 0, input); + throw nvae; + } + + switch (alt24) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:516:17: FTSPHRASE ( ( slop )=> slop )? + { + FTSPHRASE64=(Token)match(input,FTSPHRASE,FOLLOW_FTSPHRASE_in_ftsTermOrPhrase2720); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_FTSPHRASE.add(FTSPHRASE64); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:516:27: ( ( slop )=> slop )? + int alt22=2; + int LA22_0 = input.LA(1); + if ( (LA22_0==TILDA) ) { + int LA22_1 = input.LA(2); + if ( (LA22_1==DECIMAL_INTEGER_LITERAL) ) { + int LA22_3 = input.LA(3); + if ( (synpred9_FTS()) ) { + alt22=1; + } + } + } + switch (alt22) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:516:28: ( slop )=> slop + { + pushFollow(FOLLOW_slop_in_ftsTermOrPhrase2728); + slop65=slop(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_slop.add(slop65.getTree()); + } + break; + + } + + // AST REWRITE + // elements: fieldReference, FTSPHRASE, slop + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 517:17: -> ^( PHRASE FTSPHRASE fieldReference ( slop )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:517:20: ^( PHRASE FTSPHRASE fieldReference ( slop )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PHRASE, "PHRASE"), root_1); + adaptor.addChild(root_1, stream_FTSPHRASE.nextNode()); + adaptor.addChild(root_1, stream_fieldReference.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:517:54: ( slop )? + if ( stream_slop.hasNext() ) { + adaptor.addChild(root_1, stream_slop.nextTree()); + } + stream_slop.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:519:17: ftsWord ( ( fuzzy )=> fuzzy )? + { + pushFollow(FOLLOW_ftsWord_in_ftsTermOrPhrase2795); + ftsWord66=ftsWord(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsWord.add(ftsWord66.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:519:25: ( ( fuzzy )=> fuzzy )? + int alt23=2; + int LA23_0 = input.LA(1); + if ( (LA23_0==TILDA) ) { + int LA23_1 = input.LA(2); + if ( (LA23_1==DECIMAL_INTEGER_LITERAL) ) { + int LA23_3 = input.LA(3); + if ( (synpred10_FTS()) ) { + alt23=1; + } + } + else if ( (LA23_1==FLOATING_POINT_LITERAL) ) { + int LA23_4 = input.LA(3); + if ( (synpred10_FTS()) ) { + alt23=1; + } + } + } + switch (alt23) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:519:26: ( fuzzy )=> fuzzy + { + pushFollow(FOLLOW_fuzzy_in_ftsTermOrPhrase2804); + fuzzy67=fuzzy(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fuzzy.add(fuzzy67.getTree()); + } + break; + + } + + // AST REWRITE + // elements: ftsWord, fuzzy, fieldReference + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 520:17: -> ^( TERM ftsWord fieldReference ( fuzzy )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:520:20: ^( TERM ftsWord fieldReference ( fuzzy )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(TERM, "TERM"), root_1); + adaptor.addChild(root_1, stream_ftsWord.nextTree()); + adaptor.addChild(root_1, stream_fieldReference.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:520:50: ( fuzzy )? + if ( stream_fuzzy.hasNext() ) { + adaptor.addChild(root_1, stream_fuzzy.nextTree()); + } + stream_fuzzy.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:523:9: FTSPHRASE ( ( slop )=> slop )? + { + FTSPHRASE68=(Token)match(input,FTSPHRASE,FOLLOW_FTSPHRASE_in_ftsTermOrPhrase2865); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_FTSPHRASE.add(FTSPHRASE68); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:523:19: ( ( slop )=> slop )? + int alt25=2; + int LA25_0 = input.LA(1); + if ( (LA25_0==TILDA) ) { + int LA25_1 = input.LA(2); + if ( (LA25_1==DECIMAL_INTEGER_LITERAL) ) { + int LA25_3 = input.LA(3); + if ( (synpred11_FTS()) ) { + alt25=1; + } + } + } + switch (alt25) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:523:20: ( slop )=> slop + { + pushFollow(FOLLOW_slop_in_ftsTermOrPhrase2873); + slop69=slop(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_slop.add(slop69.getTree()); + } + break; + + } + + // AST REWRITE + // elements: FTSPHRASE, slop + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 524:17: -> ^( PHRASE FTSPHRASE ( slop )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:524:20: ^( PHRASE FTSPHRASE ( slop )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PHRASE, "PHRASE"), root_1); + adaptor.addChild(root_1, stream_FTSPHRASE.nextNode()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:524:39: ( slop )? + if ( stream_slop.hasNext() ) { + adaptor.addChild(root_1, stream_slop.nextTree()); + } + stream_slop.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:526:9: ftsWord ( ( fuzzy )=> fuzzy )? + { + pushFollow(FOLLOW_ftsWord_in_ftsTermOrPhrase2923); + ftsWord70=ftsWord(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsWord.add(ftsWord70.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:526:17: ( ( fuzzy )=> fuzzy )? + int alt26=2; + int LA26_0 = input.LA(1); + if ( (LA26_0==TILDA) ) { + int LA26_1 = input.LA(2); + if ( (LA26_1==DECIMAL_INTEGER_LITERAL) ) { + int LA26_3 = input.LA(3); + if ( (synpred12_FTS()) ) { + alt26=1; + } + } + else if ( (LA26_1==FLOATING_POINT_LITERAL) ) { + int LA26_4 = input.LA(3); + if ( (synpred12_FTS()) ) { + alt26=1; + } + } + } + switch (alt26) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:526:18: ( fuzzy )=> fuzzy + { + pushFollow(FOLLOW_fuzzy_in_ftsTermOrPhrase2932); + fuzzy71=fuzzy(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fuzzy.add(fuzzy71.getTree()); + } + break; + + } + + // AST REWRITE + // elements: ftsWord, fuzzy + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 527:17: -> ^( TERM ftsWord ( fuzzy )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:527:20: ^( TERM ftsWord ( fuzzy )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(TERM, "TERM"), root_1); + adaptor.addChild(root_1, stream_ftsWord.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:527:35: ( fuzzy )? + if ( stream_fuzzy.hasNext() ) { + adaptor.addChild(root_1, stream_fuzzy.nextTree()); + } + stream_fuzzy.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsTermOrPhrase" + + + public static class ftsExactTermOrPhrase_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsExactTermOrPhrase" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:531:1: ftsExactTermOrPhrase : EQUALS ( ( fieldReference COLON )=> fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( EXACT_PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( EXACT_TERM ftsWord fieldReference ( fuzzy )? ) ) | FTSPHRASE ( ( slop )=> slop )? -> ^( EXACT_PHRASE FTSPHRASE ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( EXACT_TERM ftsWord ( fuzzy )? ) ) ; + public final FTSParser.ftsExactTermOrPhrase_return ftsExactTermOrPhrase() throws RecognitionException { + FTSParser.ftsExactTermOrPhrase_return retval = new FTSParser.ftsExactTermOrPhrase_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token EQUALS72=null; + Token COLON74=null; + Token FTSPHRASE75=null; + Token FTSPHRASE79=null; + ParserRuleReturnScope fieldReference73 =null; + ParserRuleReturnScope slop76 =null; + ParserRuleReturnScope ftsWord77 =null; + ParserRuleReturnScope fuzzy78 =null; + ParserRuleReturnScope slop80 =null; + ParserRuleReturnScope ftsWord81 =null; + ParserRuleReturnScope fuzzy82 =null; + + Object EQUALS72_tree=null; + Object COLON74_tree=null; + Object FTSPHRASE75_tree=null; + Object FTSPHRASE79_tree=null; + RewriteRuleTokenStream stream_FTSPHRASE=new RewriteRuleTokenStream(adaptor,"token FTSPHRASE"); + RewriteRuleTokenStream stream_EQUALS=new RewriteRuleTokenStream(adaptor,"token EQUALS"); + RewriteRuleTokenStream stream_COLON=new RewriteRuleTokenStream(adaptor,"token COLON"); + RewriteRuleSubtreeStream stream_ftsWord=new RewriteRuleSubtreeStream(adaptor,"rule ftsWord"); + RewriteRuleSubtreeStream stream_fieldReference=new RewriteRuleSubtreeStream(adaptor,"rule fieldReference"); + RewriteRuleSubtreeStream stream_fuzzy=new RewriteRuleSubtreeStream(adaptor,"rule fuzzy"); + RewriteRuleSubtreeStream stream_slop=new RewriteRuleSubtreeStream(adaptor,"rule slop"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:532:9: ( EQUALS ( ( fieldReference COLON )=> fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( EXACT_PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( EXACT_TERM ftsWord fieldReference ( fuzzy )? ) ) | FTSPHRASE ( ( slop )=> slop )? -> ^( EXACT_PHRASE FTSPHRASE ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( EXACT_TERM ftsWord ( fuzzy )? ) ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:533:9: EQUALS ( ( fieldReference COLON )=> fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( EXACT_PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( EXACT_TERM ftsWord fieldReference ( fuzzy )? ) ) | FTSPHRASE ( ( slop )=> slop )? -> ^( EXACT_PHRASE FTSPHRASE ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( EXACT_TERM ftsWord ( fuzzy )? ) ) + { + EQUALS72=(Token)match(input,EQUALS,FOLLOW_EQUALS_in_ftsExactTermOrPhrase3011); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_EQUALS.add(EQUALS72); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:534:9: ( ( fieldReference COLON )=> fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( EXACT_PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( EXACT_TERM ftsWord fieldReference ( fuzzy )? ) ) | FTSPHRASE ( ( slop )=> slop )? -> ^( EXACT_PHRASE FTSPHRASE ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( EXACT_TERM ftsWord ( fuzzy )? ) ) + int alt33=3; + alt33 = dfa33.predict(input); + switch (alt33) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:535:9: ( fieldReference COLON )=> fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( EXACT_PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( EXACT_TERM ftsWord fieldReference ( fuzzy )? ) ) + { + pushFollow(FOLLOW_fieldReference_in_ftsExactTermOrPhrase3039); + fieldReference73=fieldReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fieldReference.add(fieldReference73.getTree()); + COLON74=(Token)match(input,COLON,FOLLOW_COLON_in_ftsExactTermOrPhrase3041); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_COLON.add(COLON74); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:536:9: ( FTSPHRASE ( ( slop )=> slop )? -> ^( EXACT_PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( EXACT_TERM ftsWord fieldReference ( fuzzy )? ) ) + int alt30=2; + int LA30_0 = input.LA(1); + if ( (LA30_0==FTSPHRASE) ) { + alt30=1; + } + else if ( (LA30_0==COMMA||LA30_0==DATETIME||LA30_0==DECIMAL_INTEGER_LITERAL||LA30_0==DOT||LA30_0==FLOATING_POINT_LITERAL||(LA30_0 >= FTSPRE && LA30_0 <= FTSWORD)||LA30_0==ID||LA30_0==NOT||LA30_0==QUESTION_MARK||LA30_0==STAR||LA30_0==TO||LA30_0==URI) ) { + alt30=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 30, 0, input); + throw nvae; + } + + switch (alt30) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:537:17: FTSPHRASE ( ( slop )=> slop )? + { + FTSPHRASE75=(Token)match(input,FTSPHRASE,FOLLOW_FTSPHRASE_in_ftsExactTermOrPhrase3069); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_FTSPHRASE.add(FTSPHRASE75); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:537:27: ( ( slop )=> slop )? + int alt28=2; + int LA28_0 = input.LA(1); + if ( (LA28_0==TILDA) ) { + int LA28_1 = input.LA(2); + if ( (LA28_1==DECIMAL_INTEGER_LITERAL) ) { + int LA28_3 = input.LA(3); + if ( (synpred14_FTS()) ) { + alt28=1; + } + } + } + switch (alt28) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:537:28: ( slop )=> slop + { + pushFollow(FOLLOW_slop_in_ftsExactTermOrPhrase3077); + slop76=slop(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_slop.add(slop76.getTree()); + } + break; + + } + + // AST REWRITE + // elements: FTSPHRASE, fieldReference, slop + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 538:17: -> ^( EXACT_PHRASE FTSPHRASE fieldReference ( slop )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:538:20: ^( EXACT_PHRASE FTSPHRASE fieldReference ( slop )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(EXACT_PHRASE, "EXACT_PHRASE"), root_1); + adaptor.addChild(root_1, stream_FTSPHRASE.nextNode()); + adaptor.addChild(root_1, stream_fieldReference.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:538:60: ( slop )? + if ( stream_slop.hasNext() ) { + adaptor.addChild(root_1, stream_slop.nextTree()); + } + stream_slop.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:540:17: ftsWord ( ( fuzzy )=> fuzzy )? + { + pushFollow(FOLLOW_ftsWord_in_ftsExactTermOrPhrase3144); + ftsWord77=ftsWord(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsWord.add(ftsWord77.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:540:25: ( ( fuzzy )=> fuzzy )? + int alt29=2; + int LA29_0 = input.LA(1); + if ( (LA29_0==TILDA) ) { + int LA29_1 = input.LA(2); + if ( (LA29_1==DECIMAL_INTEGER_LITERAL) ) { + int LA29_3 = input.LA(3); + if ( (synpred15_FTS()) ) { + alt29=1; + } + } + else if ( (LA29_1==FLOATING_POINT_LITERAL) ) { + int LA29_4 = input.LA(3); + if ( (synpred15_FTS()) ) { + alt29=1; + } + } + } + switch (alt29) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:540:26: ( fuzzy )=> fuzzy + { + pushFollow(FOLLOW_fuzzy_in_ftsExactTermOrPhrase3153); + fuzzy78=fuzzy(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fuzzy.add(fuzzy78.getTree()); + } + break; + + } + + // AST REWRITE + // elements: fieldReference, fuzzy, ftsWord + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 541:17: -> ^( EXACT_TERM ftsWord fieldReference ( fuzzy )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:541:20: ^( EXACT_TERM ftsWord fieldReference ( fuzzy )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(EXACT_TERM, "EXACT_TERM"), root_1); + adaptor.addChild(root_1, stream_ftsWord.nextTree()); + adaptor.addChild(root_1, stream_fieldReference.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:541:56: ( fuzzy )? + if ( stream_fuzzy.hasNext() ) { + adaptor.addChild(root_1, stream_fuzzy.nextTree()); + } + stream_fuzzy.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:544:9: FTSPHRASE ( ( slop )=> slop )? + { + FTSPHRASE79=(Token)match(input,FTSPHRASE,FOLLOW_FTSPHRASE_in_ftsExactTermOrPhrase3214); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_FTSPHRASE.add(FTSPHRASE79); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:544:19: ( ( slop )=> slop )? + int alt31=2; + int LA31_0 = input.LA(1); + if ( (LA31_0==TILDA) ) { + int LA31_1 = input.LA(2); + if ( (LA31_1==DECIMAL_INTEGER_LITERAL) ) { + int LA31_3 = input.LA(3); + if ( (synpred16_FTS()) ) { + alt31=1; + } + } + } + switch (alt31) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:544:20: ( slop )=> slop + { + pushFollow(FOLLOW_slop_in_ftsExactTermOrPhrase3222); + slop80=slop(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_slop.add(slop80.getTree()); + } + break; + + } + + // AST REWRITE + // elements: slop, FTSPHRASE + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 545:17: -> ^( EXACT_PHRASE FTSPHRASE ( slop )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:545:20: ^( EXACT_PHRASE FTSPHRASE ( slop )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(EXACT_PHRASE, "EXACT_PHRASE"), root_1); + adaptor.addChild(root_1, stream_FTSPHRASE.nextNode()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:545:45: ( slop )? + if ( stream_slop.hasNext() ) { + adaptor.addChild(root_1, stream_slop.nextTree()); + } + stream_slop.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:547:9: ftsWord ( ( fuzzy )=> fuzzy )? + { + pushFollow(FOLLOW_ftsWord_in_ftsExactTermOrPhrase3272); + ftsWord81=ftsWord(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsWord.add(ftsWord81.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:547:17: ( ( fuzzy )=> fuzzy )? + int alt32=2; + int LA32_0 = input.LA(1); + if ( (LA32_0==TILDA) ) { + int LA32_1 = input.LA(2); + if ( (LA32_1==DECIMAL_INTEGER_LITERAL) ) { + int LA32_3 = input.LA(3); + if ( (synpred17_FTS()) ) { + alt32=1; + } + } + else if ( (LA32_1==FLOATING_POINT_LITERAL) ) { + int LA32_4 = input.LA(3); + if ( (synpred17_FTS()) ) { + alt32=1; + } + } + } + switch (alt32) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:547:18: ( fuzzy )=> fuzzy + { + pushFollow(FOLLOW_fuzzy_in_ftsExactTermOrPhrase3281); + fuzzy82=fuzzy(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fuzzy.add(fuzzy82.getTree()); + } + break; + + } + + // AST REWRITE + // elements: fuzzy, ftsWord + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 548:17: -> ^( EXACT_TERM ftsWord ( fuzzy )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:548:20: ^( EXACT_TERM ftsWord ( fuzzy )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(EXACT_TERM, "EXACT_TERM"), root_1); + adaptor.addChild(root_1, stream_ftsWord.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:548:41: ( fuzzy )? + if ( stream_fuzzy.hasNext() ) { + adaptor.addChild(root_1, stream_fuzzy.nextTree()); + } + stream_fuzzy.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsExactTermOrPhrase" + + + public static class ftsTokenisedTermOrPhrase_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsTokenisedTermOrPhrase" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:553:1: ftsTokenisedTermOrPhrase : TILDA ( ( fieldReference COLON )=> fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord fieldReference ( fuzzy )? ) ) | FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord ( fuzzy )? ) ) ; + public final FTSParser.ftsTokenisedTermOrPhrase_return ftsTokenisedTermOrPhrase() throws RecognitionException { + FTSParser.ftsTokenisedTermOrPhrase_return retval = new FTSParser.ftsTokenisedTermOrPhrase_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token TILDA83=null; + Token COLON85=null; + Token FTSPHRASE86=null; + Token FTSPHRASE90=null; + ParserRuleReturnScope fieldReference84 =null; + ParserRuleReturnScope slop87 =null; + ParserRuleReturnScope ftsWord88 =null; + ParserRuleReturnScope fuzzy89 =null; + ParserRuleReturnScope slop91 =null; + ParserRuleReturnScope ftsWord92 =null; + ParserRuleReturnScope fuzzy93 =null; + + Object TILDA83_tree=null; + Object COLON85_tree=null; + Object FTSPHRASE86_tree=null; + Object FTSPHRASE90_tree=null; + RewriteRuleTokenStream stream_FTSPHRASE=new RewriteRuleTokenStream(adaptor,"token FTSPHRASE"); + RewriteRuleTokenStream stream_TILDA=new RewriteRuleTokenStream(adaptor,"token TILDA"); + RewriteRuleTokenStream stream_COLON=new RewriteRuleTokenStream(adaptor,"token COLON"); + RewriteRuleSubtreeStream stream_ftsWord=new RewriteRuleSubtreeStream(adaptor,"rule ftsWord"); + RewriteRuleSubtreeStream stream_fieldReference=new RewriteRuleSubtreeStream(adaptor,"rule fieldReference"); + RewriteRuleSubtreeStream stream_fuzzy=new RewriteRuleSubtreeStream(adaptor,"rule fuzzy"); + RewriteRuleSubtreeStream stream_slop=new RewriteRuleSubtreeStream(adaptor,"rule slop"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:554:9: ( TILDA ( ( fieldReference COLON )=> fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord fieldReference ( fuzzy )? ) ) | FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord ( fuzzy )? ) ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:555:9: TILDA ( ( fieldReference COLON )=> fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord fieldReference ( fuzzy )? ) ) | FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord ( fuzzy )? ) ) + { + TILDA83=(Token)match(input,TILDA,FOLLOW_TILDA_in_ftsTokenisedTermOrPhrase3362); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_TILDA.add(TILDA83); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:556:9: ( ( fieldReference COLON )=> fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord fieldReference ( fuzzy )? ) ) | FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord ( fuzzy )? ) ) + int alt39=3; + alt39 = dfa39.predict(input); + switch (alt39) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:557:9: ( fieldReference COLON )=> fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord fieldReference ( fuzzy )? ) ) + { + pushFollow(FOLLOW_fieldReference_in_ftsTokenisedTermOrPhrase3390); + fieldReference84=fieldReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fieldReference.add(fieldReference84.getTree()); + COLON85=(Token)match(input,COLON,FOLLOW_COLON_in_ftsTokenisedTermOrPhrase3392); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_COLON.add(COLON85); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:558:9: ( FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord fieldReference ( fuzzy )? ) ) + int alt36=2; + int LA36_0 = input.LA(1); + if ( (LA36_0==FTSPHRASE) ) { + alt36=1; + } + else if ( (LA36_0==COMMA||LA36_0==DATETIME||LA36_0==DECIMAL_INTEGER_LITERAL||LA36_0==DOT||LA36_0==FLOATING_POINT_LITERAL||(LA36_0 >= FTSPRE && LA36_0 <= FTSWORD)||LA36_0==ID||LA36_0==NOT||LA36_0==QUESTION_MARK||LA36_0==STAR||LA36_0==TO||LA36_0==URI) ) { + alt36=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 36, 0, input); + throw nvae; + } + + switch (alt36) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:559:17: FTSPHRASE ( ( slop )=> slop )? + { + FTSPHRASE86=(Token)match(input,FTSPHRASE,FOLLOW_FTSPHRASE_in_ftsTokenisedTermOrPhrase3420); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_FTSPHRASE.add(FTSPHRASE86); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:559:27: ( ( slop )=> slop )? + int alt34=2; + int LA34_0 = input.LA(1); + if ( (LA34_0==TILDA) ) { + int LA34_1 = input.LA(2); + if ( (LA34_1==DECIMAL_INTEGER_LITERAL) ) { + int LA34_3 = input.LA(3); + if ( (synpred19_FTS()) ) { + alt34=1; + } + } + } + switch (alt34) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:559:28: ( slop )=> slop + { + pushFollow(FOLLOW_slop_in_ftsTokenisedTermOrPhrase3428); + slop87=slop(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_slop.add(slop87.getTree()); + } + break; + + } + + // AST REWRITE + // elements: FTSPHRASE, fieldReference, slop + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 560:17: -> ^( PHRASE FTSPHRASE fieldReference ( slop )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:560:20: ^( PHRASE FTSPHRASE fieldReference ( slop )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PHRASE, "PHRASE"), root_1); + adaptor.addChild(root_1, stream_FTSPHRASE.nextNode()); + adaptor.addChild(root_1, stream_fieldReference.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:560:54: ( slop )? + if ( stream_slop.hasNext() ) { + adaptor.addChild(root_1, stream_slop.nextTree()); + } + stream_slop.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:562:17: ftsWord ( ( fuzzy )=> fuzzy )? + { + pushFollow(FOLLOW_ftsWord_in_ftsTokenisedTermOrPhrase3495); + ftsWord88=ftsWord(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsWord.add(ftsWord88.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:562:25: ( ( fuzzy )=> fuzzy )? + int alt35=2; + int LA35_0 = input.LA(1); + if ( (LA35_0==TILDA) ) { + int LA35_1 = input.LA(2); + if ( (LA35_1==DECIMAL_INTEGER_LITERAL) ) { + int LA35_3 = input.LA(3); + if ( (synpred20_FTS()) ) { + alt35=1; + } + } + else if ( (LA35_1==FLOATING_POINT_LITERAL) ) { + int LA35_4 = input.LA(3); + if ( (synpred20_FTS()) ) { + alt35=1; + } + } + } + switch (alt35) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:562:26: ( fuzzy )=> fuzzy + { + pushFollow(FOLLOW_fuzzy_in_ftsTokenisedTermOrPhrase3504); + fuzzy89=fuzzy(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fuzzy.add(fuzzy89.getTree()); + } + break; + + } + + // AST REWRITE + // elements: fuzzy, ftsWord, fieldReference + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 563:17: -> ^( TERM ftsWord fieldReference ( fuzzy )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:563:20: ^( TERM ftsWord fieldReference ( fuzzy )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(TERM, "TERM"), root_1); + adaptor.addChild(root_1, stream_ftsWord.nextTree()); + adaptor.addChild(root_1, stream_fieldReference.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:563:50: ( fuzzy )? + if ( stream_fuzzy.hasNext() ) { + adaptor.addChild(root_1, stream_fuzzy.nextTree()); + } + stream_fuzzy.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:566:9: FTSPHRASE ( ( slop )=> slop )? + { + FTSPHRASE90=(Token)match(input,FTSPHRASE,FOLLOW_FTSPHRASE_in_ftsTokenisedTermOrPhrase3565); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_FTSPHRASE.add(FTSPHRASE90); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:566:19: ( ( slop )=> slop )? + int alt37=2; + int LA37_0 = input.LA(1); + if ( (LA37_0==TILDA) ) { + int LA37_1 = input.LA(2); + if ( (LA37_1==DECIMAL_INTEGER_LITERAL) ) { + int LA37_3 = input.LA(3); + if ( (synpred21_FTS()) ) { + alt37=1; + } + } + } + switch (alt37) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:566:20: ( slop )=> slop + { + pushFollow(FOLLOW_slop_in_ftsTokenisedTermOrPhrase3573); + slop91=slop(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_slop.add(slop91.getTree()); + } + break; + + } + + // AST REWRITE + // elements: slop, FTSPHRASE + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 567:17: -> ^( PHRASE FTSPHRASE ( slop )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:567:20: ^( PHRASE FTSPHRASE ( slop )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PHRASE, "PHRASE"), root_1); + adaptor.addChild(root_1, stream_FTSPHRASE.nextNode()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:567:39: ( slop )? + if ( stream_slop.hasNext() ) { + adaptor.addChild(root_1, stream_slop.nextTree()); + } + stream_slop.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:569:9: ftsWord ( ( fuzzy )=> fuzzy )? + { + pushFollow(FOLLOW_ftsWord_in_ftsTokenisedTermOrPhrase3623); + ftsWord92=ftsWord(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsWord.add(ftsWord92.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:569:17: ( ( fuzzy )=> fuzzy )? + int alt38=2; + int LA38_0 = input.LA(1); + if ( (LA38_0==TILDA) ) { + int LA38_1 = input.LA(2); + if ( (LA38_1==DECIMAL_INTEGER_LITERAL) ) { + int LA38_3 = input.LA(3); + if ( (synpred22_FTS()) ) { + alt38=1; + } + } + else if ( (LA38_1==FLOATING_POINT_LITERAL) ) { + int LA38_4 = input.LA(3); + if ( (synpred22_FTS()) ) { + alt38=1; + } + } + } + switch (alt38) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:569:18: ( fuzzy )=> fuzzy + { + pushFollow(FOLLOW_fuzzy_in_ftsTokenisedTermOrPhrase3632); + fuzzy93=fuzzy(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fuzzy.add(fuzzy93.getTree()); + } + break; + + } + + // AST REWRITE + // elements: ftsWord, fuzzy + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 570:17: -> ^( TERM ftsWord ( fuzzy )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:570:20: ^( TERM ftsWord ( fuzzy )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(TERM, "TERM"), root_1); + adaptor.addChild(root_1, stream_ftsWord.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:570:35: ( fuzzy )? + if ( stream_fuzzy.hasNext() ) { + adaptor.addChild(root_1, stream_fuzzy.nextTree()); + } + stream_fuzzy.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsTokenisedTermOrPhrase" + + + public static class cmisTerm_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "cmisTerm" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:575:1: cmisTerm : ftsWord -> ftsWord ; + public final FTSParser.cmisTerm_return cmisTerm() throws RecognitionException { + FTSParser.cmisTerm_return retval = new FTSParser.cmisTerm_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope ftsWord94 =null; + + RewriteRuleSubtreeStream stream_ftsWord=new RewriteRuleSubtreeStream(adaptor,"rule ftsWord"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:576:9: ( ftsWord -> ftsWord ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:577:9: ftsWord + { + pushFollow(FOLLOW_ftsWord_in_cmisTerm3705); + ftsWord94=ftsWord(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsWord.add(ftsWord94.getTree()); + // AST REWRITE + // elements: ftsWord + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 578:17: -> ftsWord + { + adaptor.addChild(root_0, stream_ftsWord.nextTree()); + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "cmisTerm" + + + public static class cmisPhrase_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "cmisPhrase" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:582:1: cmisPhrase : FTSPHRASE -> FTSPHRASE ; + public final FTSParser.cmisPhrase_return cmisPhrase() throws RecognitionException { + FTSParser.cmisPhrase_return retval = new FTSParser.cmisPhrase_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token FTSPHRASE95=null; + + Object FTSPHRASE95_tree=null; + RewriteRuleTokenStream stream_FTSPHRASE=new RewriteRuleTokenStream(adaptor,"token FTSPHRASE"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:583:9: ( FTSPHRASE -> FTSPHRASE ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:584:9: FTSPHRASE + { + FTSPHRASE95=(Token)match(input,FTSPHRASE,FOLLOW_FTSPHRASE_in_cmisPhrase3759); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_FTSPHRASE.add(FTSPHRASE95); + + // AST REWRITE + // elements: FTSPHRASE + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 585:17: -> FTSPHRASE + { + adaptor.addChild(root_0, stream_FTSPHRASE.nextNode()); + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "cmisPhrase" + + + public static class ftsRange_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsRange" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:589:1: ftsRange : ( fieldReference COLON )? ftsFieldGroupRange -> ftsFieldGroupRange ( fieldReference )? ; + public final FTSParser.ftsRange_return ftsRange() throws RecognitionException { + FTSParser.ftsRange_return retval = new FTSParser.ftsRange_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token COLON97=null; + ParserRuleReturnScope fieldReference96 =null; + ParserRuleReturnScope ftsFieldGroupRange98 =null; + + Object COLON97_tree=null; + RewriteRuleTokenStream stream_COLON=new RewriteRuleTokenStream(adaptor,"token COLON"); + RewriteRuleSubtreeStream stream_ftsFieldGroupRange=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupRange"); + RewriteRuleSubtreeStream stream_fieldReference=new RewriteRuleSubtreeStream(adaptor,"rule fieldReference"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:590:9: ( ( fieldReference COLON )? ftsFieldGroupRange -> ftsFieldGroupRange ( fieldReference )? ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:591:9: ( fieldReference COLON )? ftsFieldGroupRange + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:591:9: ( fieldReference COLON )? + int alt40=2; + switch ( input.LA(1) ) { + case AND: + case AT: + case NOT: + case OR: + case TO: + { + alt40=1; + } + break; + case ID: + { + int LA40_2 = input.LA(2); + if ( (LA40_2==COLON||LA40_2==DOT) ) { + alt40=1; + } + } + break; + case URI: + { + switch ( input.LA(2) ) { + case ID: + { + int LA40_5 = input.LA(3); + if ( (LA40_5==DOT) ) { + int LA40_10 = input.LA(4); + if ( (LA40_10==ID) ) { + int LA40_11 = input.LA(5); + if ( (LA40_11==COLON) ) { + alt40=1; + } + } + } + else if ( (LA40_5==COLON) ) { + alt40=1; + } + } + break; + case TO: + { + int LA40_6 = input.LA(3); + if ( (LA40_6==COLON) ) { + alt40=1; + } + } + break; + case OR: + { + int LA40_7 = input.LA(3); + if ( (LA40_7==COLON) ) { + alt40=1; + } + } + break; + case AND: + { + int LA40_8 = input.LA(3); + if ( (LA40_8==COLON) ) { + alt40=1; + } + } + break; + case NOT: + { + int LA40_9 = input.LA(3); + if ( (LA40_9==COLON) ) { + alt40=1; + } + } + break; + } + } + break; + } + switch (alt40) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:591:10: fieldReference COLON + { + pushFollow(FOLLOW_fieldReference_in_ftsRange3814); + fieldReference96=fieldReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fieldReference.add(fieldReference96.getTree()); + COLON97=(Token)match(input,COLON,FOLLOW_COLON_in_ftsRange3816); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_COLON.add(COLON97); + + } + break; + + } + + pushFollow(FOLLOW_ftsFieldGroupRange_in_ftsRange3820); + ftsFieldGroupRange98=ftsFieldGroupRange(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupRange.add(ftsFieldGroupRange98.getTree()); + // AST REWRITE + // elements: fieldReference, ftsFieldGroupRange + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 592:17: -> ftsFieldGroupRange ( fieldReference )? + { + adaptor.addChild(root_0, stream_ftsFieldGroupRange.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:592:39: ( fieldReference )? + if ( stream_fieldReference.hasNext() ) { + adaptor.addChild(root_0, stream_fieldReference.nextTree()); + } + stream_fieldReference.reset(); + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsRange" + + + public static class ftsFieldGroup_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroup" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:595:1: ftsFieldGroup : fieldReference COLON LPAREN ftsFieldGroupDisjunction RPAREN -> ^( FIELD_GROUP fieldReference ftsFieldGroupDisjunction ) ; + public final FTSParser.ftsFieldGroup_return ftsFieldGroup() throws RecognitionException { + FTSParser.ftsFieldGroup_return retval = new FTSParser.ftsFieldGroup_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token COLON100=null; + Token LPAREN101=null; + Token RPAREN103=null; + ParserRuleReturnScope fieldReference99 =null; + ParserRuleReturnScope ftsFieldGroupDisjunction102 =null; + + Object COLON100_tree=null; + Object LPAREN101_tree=null; + Object RPAREN103_tree=null; + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleTokenStream stream_COLON=new RewriteRuleTokenStream(adaptor,"token COLON"); + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleSubtreeStream stream_ftsFieldGroupDisjunction=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupDisjunction"); + RewriteRuleSubtreeStream stream_fieldReference=new RewriteRuleSubtreeStream(adaptor,"rule fieldReference"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:596:9: ( fieldReference COLON LPAREN ftsFieldGroupDisjunction RPAREN -> ^( FIELD_GROUP fieldReference ftsFieldGroupDisjunction ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:597:9: fieldReference COLON LPAREN ftsFieldGroupDisjunction RPAREN + { + pushFollow(FOLLOW_fieldReference_in_ftsFieldGroup3876); + fieldReference99=fieldReference(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fieldReference.add(fieldReference99.getTree()); + COLON100=(Token)match(input,COLON,FOLLOW_COLON_in_ftsFieldGroup3878); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_COLON.add(COLON100); + + LPAREN101=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_ftsFieldGroup3880); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(LPAREN101); + + pushFollow(FOLLOW_ftsFieldGroupDisjunction_in_ftsFieldGroup3882); + ftsFieldGroupDisjunction102=ftsFieldGroupDisjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupDisjunction.add(ftsFieldGroupDisjunction102.getTree()); + RPAREN103=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_ftsFieldGroup3884); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(RPAREN103); + + // AST REWRITE + // elements: fieldReference, ftsFieldGroupDisjunction + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 598:17: -> ^( FIELD_GROUP fieldReference ftsFieldGroupDisjunction ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:599:25: ^( FIELD_GROUP fieldReference ftsFieldGroupDisjunction ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FIELD_GROUP, "FIELD_GROUP"), root_1); + adaptor.addChild(root_1, stream_fieldReference.nextTree()); + adaptor.addChild(root_1, stream_ftsFieldGroupDisjunction.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroup" + + + public static class ftsFieldGroupDisjunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupDisjunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:602:1: ftsFieldGroupDisjunction : ({...}? ftsFieldGroupExplicitDisjunction |{...}? ftsFieldGroupImplicitDisjunction ); + public final FTSParser.ftsFieldGroupDisjunction_return ftsFieldGroupDisjunction() throws RecognitionException { + FTSParser.ftsFieldGroupDisjunction_return retval = new FTSParser.ftsFieldGroupDisjunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope ftsFieldGroupExplicitDisjunction104 =null; + ParserRuleReturnScope ftsFieldGroupImplicitDisjunction105 =null; + + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:603:9: ({...}? ftsFieldGroupExplicitDisjunction |{...}? ftsFieldGroupImplicitDisjunction ) + int alt41=2; + switch ( input.LA(1) ) { + case AMP: + case AND: + { + alt41=1; + } + break; + case NOT: + { + int LA41_3 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 3, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case ID: + { + int LA41_4 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 4, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case FTSWORD: + { + int LA41_5 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 5, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case FTSPRE: + { + int LA41_6 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 6, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case FTSWILD: + { + int LA41_7 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 7, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case EXCLAMATION: + { + int LA41_8 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 8, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case TO: + { + int LA41_9 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 9, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case DECIMAL_INTEGER_LITERAL: + { + int LA41_10 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 10, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case FLOATING_POINT_LITERAL: + { + int LA41_11 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 11, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case DATETIME: + { + int LA41_12 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 12, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case STAR: + { + int LA41_13 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 13, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case URI: + { + int LA41_14 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 14, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case COMMA: + case DOT: + { + int LA41_15 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 15, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case QUESTION_MARK: + { + int LA41_16 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 16, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case EQUALS: + { + int LA41_17 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 17, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case FTSPHRASE: + { + int LA41_18 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 18, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case TILDA: + { + int LA41_19 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 19, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case LSQUARE: + { + int LA41_20 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 20, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case LT: + { + int LA41_21 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 21, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case LPAREN: + { + int LA41_22 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 22, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case PLUS: + { + int LA41_23 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 23, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case BAR: + { + int LA41_24 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 24, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case MINUS: + { + int LA41_25 = input.LA(2); + if ( ((defaultFieldConjunction() == true)) ) { + alt41=1; + } + else if ( ((defaultFieldConjunction() == false)) ) { + alt41=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 41, 25, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case OR: + { + alt41=2; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 41, 0, input); + throw nvae; + } + switch (alt41) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:604:9: {...}? ftsFieldGroupExplicitDisjunction + { + root_0 = (Object)adaptor.nil(); + + + if ( !((defaultFieldConjunction() == true)) ) { + if (state.backtracking>0) {state.failed=true; return retval;} + throw new FailedPredicateException(input, "ftsFieldGroupDisjunction", "defaultFieldConjunction() == true"); + } + pushFollow(FOLLOW_ftsFieldGroupExplicitDisjunction_in_ftsFieldGroupDisjunction3969); + ftsFieldGroupExplicitDisjunction104=ftsFieldGroupExplicitDisjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsFieldGroupExplicitDisjunction104.getTree()); + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:605:11: {...}? ftsFieldGroupImplicitDisjunction + { + root_0 = (Object)adaptor.nil(); + + + if ( !((defaultFieldConjunction() == false)) ) { + if (state.backtracking>0) {state.failed=true; return retval;} + throw new FailedPredicateException(input, "ftsFieldGroupDisjunction", "defaultFieldConjunction() == false"); + } + pushFollow(FOLLOW_ftsFieldGroupImplicitDisjunction_in_ftsFieldGroupDisjunction3983); + ftsFieldGroupImplicitDisjunction105=ftsFieldGroupImplicitDisjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsFieldGroupImplicitDisjunction105.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupDisjunction" + + + public static class ftsFieldGroupExplicitDisjunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupExplicitDisjunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:608:1: ftsFieldGroupExplicitDisjunction : ftsFieldGroupImplicitConjunction ( or ftsFieldGroupImplicitConjunction )* -> ^( FIELD_DISJUNCTION ( ftsFieldGroupImplicitConjunction )+ ) ; + public final FTSParser.ftsFieldGroupExplicitDisjunction_return ftsFieldGroupExplicitDisjunction() throws RecognitionException { + FTSParser.ftsFieldGroupExplicitDisjunction_return retval = new FTSParser.ftsFieldGroupExplicitDisjunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope ftsFieldGroupImplicitConjunction106 =null; + ParserRuleReturnScope or107 =null; + ParserRuleReturnScope ftsFieldGroupImplicitConjunction108 =null; + + RewriteRuleSubtreeStream stream_ftsFieldGroupImplicitConjunction=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupImplicitConjunction"); + RewriteRuleSubtreeStream stream_or=new RewriteRuleSubtreeStream(adaptor,"rule or"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:609:9: ( ftsFieldGroupImplicitConjunction ( or ftsFieldGroupImplicitConjunction )* -> ^( FIELD_DISJUNCTION ( ftsFieldGroupImplicitConjunction )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:610:9: ftsFieldGroupImplicitConjunction ( or ftsFieldGroupImplicitConjunction )* + { + pushFollow(FOLLOW_ftsFieldGroupImplicitConjunction_in_ftsFieldGroupExplicitDisjunction4016); + ftsFieldGroupImplicitConjunction106=ftsFieldGroupImplicitConjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupImplicitConjunction.add(ftsFieldGroupImplicitConjunction106.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:610:42: ( or ftsFieldGroupImplicitConjunction )* + loop42: + while (true) { + int alt42=2; + int LA42_0 = input.LA(1); + if ( (LA42_0==BAR||LA42_0==OR) ) { + alt42=1; + } + + switch (alt42) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:610:43: or ftsFieldGroupImplicitConjunction + { + pushFollow(FOLLOW_or_in_ftsFieldGroupExplicitDisjunction4019); + or107=or(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_or.add(or107.getTree()); + pushFollow(FOLLOW_ftsFieldGroupImplicitConjunction_in_ftsFieldGroupExplicitDisjunction4021); + ftsFieldGroupImplicitConjunction108=ftsFieldGroupImplicitConjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupImplicitConjunction.add(ftsFieldGroupImplicitConjunction108.getTree()); + } + break; + + default : + break loop42; + } + } + + // AST REWRITE + // elements: ftsFieldGroupImplicitConjunction + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 611:17: -> ^( FIELD_DISJUNCTION ( ftsFieldGroupImplicitConjunction )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:612:25: ^( FIELD_DISJUNCTION ( ftsFieldGroupImplicitConjunction )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FIELD_DISJUNCTION, "FIELD_DISJUNCTION"), root_1); + if ( !(stream_ftsFieldGroupImplicitConjunction.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_ftsFieldGroupImplicitConjunction.hasNext() ) { + adaptor.addChild(root_1, stream_ftsFieldGroupImplicitConjunction.nextTree()); + } + stream_ftsFieldGroupImplicitConjunction.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupExplicitDisjunction" + + + public static class ftsFieldGroupImplicitDisjunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupImplicitDisjunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:615:1: ftsFieldGroupImplicitDisjunction : ( ( or )? ftsFieldGroupExplicitConjunction )+ -> ^( FIELD_DISJUNCTION ( ftsFieldGroupExplicitConjunction )+ ) ; + public final FTSParser.ftsFieldGroupImplicitDisjunction_return ftsFieldGroupImplicitDisjunction() throws RecognitionException { + FTSParser.ftsFieldGroupImplicitDisjunction_return retval = new FTSParser.ftsFieldGroupImplicitDisjunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope or109 =null; + ParserRuleReturnScope ftsFieldGroupExplicitConjunction110 =null; + + RewriteRuleSubtreeStream stream_or=new RewriteRuleSubtreeStream(adaptor,"rule or"); + RewriteRuleSubtreeStream stream_ftsFieldGroupExplicitConjunction=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupExplicitConjunction"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:616:9: ( ( ( or )? ftsFieldGroupExplicitConjunction )+ -> ^( FIELD_DISJUNCTION ( ftsFieldGroupExplicitConjunction )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:617:9: ( ( or )? ftsFieldGroupExplicitConjunction )+ + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:617:9: ( ( or )? ftsFieldGroupExplicitConjunction )+ + int cnt44=0; + loop44: + while (true) { + int alt44=2; + int LA44_0 = input.LA(1); + if ( (LA44_0==BAR||LA44_0==COMMA||LA44_0==DATETIME||LA44_0==DECIMAL_INTEGER_LITERAL||LA44_0==DOT||LA44_0==EQUALS||LA44_0==EXCLAMATION||LA44_0==FLOATING_POINT_LITERAL||(LA44_0 >= FTSPHRASE && LA44_0 <= FTSWORD)||LA44_0==ID||(LA44_0 >= LPAREN && LA44_0 <= LT)||LA44_0==MINUS||LA44_0==NOT||LA44_0==OR||LA44_0==PLUS||LA44_0==QUESTION_MARK||LA44_0==STAR||(LA44_0 >= TILDA && LA44_0 <= TO)||LA44_0==URI) ) { + alt44=1; + } + + switch (alt44) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:617:10: ( or )? ftsFieldGroupExplicitConjunction + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:617:10: ( or )? + int alt43=2; + int LA43_0 = input.LA(1); + if ( (LA43_0==OR) ) { + alt43=1; + } + else if ( (LA43_0==BAR) ) { + int LA43_2 = input.LA(2); + if ( (LA43_2==BAR) ) { + alt43=1; + } + } + switch (alt43) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:617:10: or + { + pushFollow(FOLLOW_or_in_ftsFieldGroupImplicitDisjunction4106); + or109=or(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_or.add(or109.getTree()); + } + break; + + } + + pushFollow(FOLLOW_ftsFieldGroupExplicitConjunction_in_ftsFieldGroupImplicitDisjunction4109); + ftsFieldGroupExplicitConjunction110=ftsFieldGroupExplicitConjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupExplicitConjunction.add(ftsFieldGroupExplicitConjunction110.getTree()); + } + break; + + default : + if ( cnt44 >= 1 ) break loop44; + if (state.backtracking>0) {state.failed=true; return retval;} + EarlyExitException eee = new EarlyExitException(44, input); + throw eee; + } + cnt44++; + } + + // AST REWRITE + // elements: ftsFieldGroupExplicitConjunction + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 618:17: -> ^( FIELD_DISJUNCTION ( ftsFieldGroupExplicitConjunction )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:619:25: ^( FIELD_DISJUNCTION ( ftsFieldGroupExplicitConjunction )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FIELD_DISJUNCTION, "FIELD_DISJUNCTION"), root_1); + if ( !(stream_ftsFieldGroupExplicitConjunction.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_ftsFieldGroupExplicitConjunction.hasNext() ) { + adaptor.addChild(root_1, stream_ftsFieldGroupExplicitConjunction.nextTree()); + } + stream_ftsFieldGroupExplicitConjunction.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupImplicitDisjunction" + + + public static class ftsFieldGroupExplicitConjunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupExplicitConjunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:626:1: ftsFieldGroupExplicitConjunction : ftsFieldGroupPrefixed ( and ftsFieldGroupPrefixed )* -> ^( FIELD_CONJUNCTION ( ftsFieldGroupPrefixed )+ ) ; + public final FTSParser.ftsFieldGroupExplicitConjunction_return ftsFieldGroupExplicitConjunction() throws RecognitionException { + FTSParser.ftsFieldGroupExplicitConjunction_return retval = new FTSParser.ftsFieldGroupExplicitConjunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope ftsFieldGroupPrefixed111 =null; + ParserRuleReturnScope and112 =null; + ParserRuleReturnScope ftsFieldGroupPrefixed113 =null; + + RewriteRuleSubtreeStream stream_ftsFieldGroupPrefixed=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupPrefixed"); + RewriteRuleSubtreeStream stream_and=new RewriteRuleSubtreeStream(adaptor,"rule and"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:627:9: ( ftsFieldGroupPrefixed ( and ftsFieldGroupPrefixed )* -> ^( FIELD_CONJUNCTION ( ftsFieldGroupPrefixed )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:628:9: ftsFieldGroupPrefixed ( and ftsFieldGroupPrefixed )* + { + pushFollow(FOLLOW_ftsFieldGroupPrefixed_in_ftsFieldGroupExplicitConjunction4196); + ftsFieldGroupPrefixed111=ftsFieldGroupPrefixed(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupPrefixed.add(ftsFieldGroupPrefixed111.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:628:31: ( and ftsFieldGroupPrefixed )* + loop45: + while (true) { + int alt45=2; + int LA45_0 = input.LA(1); + if ( ((LA45_0 >= AMP && LA45_0 <= AND)) ) { + alt45=1; + } + + switch (alt45) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:628:32: and ftsFieldGroupPrefixed + { + pushFollow(FOLLOW_and_in_ftsFieldGroupExplicitConjunction4199); + and112=and(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_and.add(and112.getTree()); + pushFollow(FOLLOW_ftsFieldGroupPrefixed_in_ftsFieldGroupExplicitConjunction4201); + ftsFieldGroupPrefixed113=ftsFieldGroupPrefixed(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupPrefixed.add(ftsFieldGroupPrefixed113.getTree()); + } + break; + + default : + break loop45; + } + } + + // AST REWRITE + // elements: ftsFieldGroupPrefixed + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 629:17: -> ^( FIELD_CONJUNCTION ( ftsFieldGroupPrefixed )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:630:25: ^( FIELD_CONJUNCTION ( ftsFieldGroupPrefixed )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FIELD_CONJUNCTION, "FIELD_CONJUNCTION"), root_1); + if ( !(stream_ftsFieldGroupPrefixed.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_ftsFieldGroupPrefixed.hasNext() ) { + adaptor.addChild(root_1, stream_ftsFieldGroupPrefixed.nextTree()); + } + stream_ftsFieldGroupPrefixed.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupExplicitConjunction" + + + public static class ftsFieldGroupImplicitConjunction_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupImplicitConjunction" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:633:1: ftsFieldGroupImplicitConjunction : ( ( and )? ftsFieldGroupPrefixed )+ -> ^( FIELD_CONJUNCTION ( ftsFieldGroupPrefixed )+ ) ; + public final FTSParser.ftsFieldGroupImplicitConjunction_return ftsFieldGroupImplicitConjunction() throws RecognitionException { + FTSParser.ftsFieldGroupImplicitConjunction_return retval = new FTSParser.ftsFieldGroupImplicitConjunction_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope and114 =null; + ParserRuleReturnScope ftsFieldGroupPrefixed115 =null; + + RewriteRuleSubtreeStream stream_ftsFieldGroupPrefixed=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupPrefixed"); + RewriteRuleSubtreeStream stream_and=new RewriteRuleSubtreeStream(adaptor,"rule and"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:634:9: ( ( ( and )? ftsFieldGroupPrefixed )+ -> ^( FIELD_CONJUNCTION ( ftsFieldGroupPrefixed )+ ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:635:9: ( ( and )? ftsFieldGroupPrefixed )+ + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:635:9: ( ( and )? ftsFieldGroupPrefixed )+ + int cnt47=0; + loop47: + while (true) { + int alt47=2; + int LA47_0 = input.LA(1); + if ( (LA47_0==BAR) ) { + int LA47_2 = input.LA(2); + if ( (LA47_2==COMMA||LA47_2==DATETIME||LA47_2==DECIMAL_INTEGER_LITERAL||LA47_2==DOT||LA47_2==EQUALS||LA47_2==FLOATING_POINT_LITERAL||(LA47_2 >= FTSPHRASE && LA47_2 <= FTSWORD)||LA47_2==ID||(LA47_2 >= LPAREN && LA47_2 <= LT)||LA47_2==NOT||LA47_2==QUESTION_MARK||LA47_2==STAR||(LA47_2 >= TILDA && LA47_2 <= TO)||LA47_2==URI) ) { + alt47=1; + } + + } + else if ( ((LA47_0 >= AMP && LA47_0 <= AND)||LA47_0==COMMA||LA47_0==DATETIME||LA47_0==DECIMAL_INTEGER_LITERAL||LA47_0==DOT||LA47_0==EQUALS||LA47_0==EXCLAMATION||LA47_0==FLOATING_POINT_LITERAL||(LA47_0 >= FTSPHRASE && LA47_0 <= FTSWORD)||LA47_0==ID||(LA47_0 >= LPAREN && LA47_0 <= LT)||LA47_0==MINUS||LA47_0==NOT||LA47_0==PLUS||LA47_0==QUESTION_MARK||LA47_0==STAR||(LA47_0 >= TILDA && LA47_0 <= TO)||LA47_0==URI) ) { + alt47=1; + } + + switch (alt47) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:635:10: ( and )? ftsFieldGroupPrefixed + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:635:10: ( and )? + int alt46=2; + int LA46_0 = input.LA(1); + if ( ((LA46_0 >= AMP && LA46_0 <= AND)) ) { + alt46=1; + } + switch (alt46) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:635:10: and + { + pushFollow(FOLLOW_and_in_ftsFieldGroupImplicitConjunction4286); + and114=and(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_and.add(and114.getTree()); + } + break; + + } + + pushFollow(FOLLOW_ftsFieldGroupPrefixed_in_ftsFieldGroupImplicitConjunction4289); + ftsFieldGroupPrefixed115=ftsFieldGroupPrefixed(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupPrefixed.add(ftsFieldGroupPrefixed115.getTree()); + } + break; + + default : + if ( cnt47 >= 1 ) break loop47; + if (state.backtracking>0) {state.failed=true; return retval;} + EarlyExitException eee = new EarlyExitException(47, input); + throw eee; + } + cnt47++; + } + + // AST REWRITE + // elements: ftsFieldGroupPrefixed + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 636:17: -> ^( FIELD_CONJUNCTION ( ftsFieldGroupPrefixed )+ ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:637:25: ^( FIELD_CONJUNCTION ( ftsFieldGroupPrefixed )+ ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FIELD_CONJUNCTION, "FIELD_CONJUNCTION"), root_1); + if ( !(stream_ftsFieldGroupPrefixed.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_ftsFieldGroupPrefixed.hasNext() ) { + adaptor.addChild(root_1, stream_ftsFieldGroupPrefixed.nextTree()); + } + stream_ftsFieldGroupPrefixed.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupImplicitConjunction" + + + public static class ftsFieldGroupPrefixed_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupPrefixed" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:640:1: ftsFieldGroupPrefixed : ( ( not )=> not ftsFieldGroupTest ( boost )? -> ^( FIELD_NEGATION ftsFieldGroupTest ( boost )? ) | ftsFieldGroupTest ( boost )? -> ^( FIELD_DEFAULT ftsFieldGroupTest ( boost )? ) | PLUS ftsFieldGroupTest ( boost )? -> ^( FIELD_MANDATORY ftsFieldGroupTest ( boost )? ) | BAR ftsFieldGroupTest ( boost )? -> ^( FIELD_OPTIONAL ftsFieldGroupTest ( boost )? ) | MINUS ftsFieldGroupTest ( boost )? -> ^( FIELD_EXCLUDE ftsFieldGroupTest ( boost )? ) ); + public final FTSParser.ftsFieldGroupPrefixed_return ftsFieldGroupPrefixed() throws RecognitionException { + FTSParser.ftsFieldGroupPrefixed_return retval = new FTSParser.ftsFieldGroupPrefixed_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token PLUS121=null; + Token BAR124=null; + Token MINUS127=null; + ParserRuleReturnScope not116 =null; + ParserRuleReturnScope ftsFieldGroupTest117 =null; + ParserRuleReturnScope boost118 =null; + ParserRuleReturnScope ftsFieldGroupTest119 =null; + ParserRuleReturnScope boost120 =null; + ParserRuleReturnScope ftsFieldGroupTest122 =null; + ParserRuleReturnScope boost123 =null; + ParserRuleReturnScope ftsFieldGroupTest125 =null; + ParserRuleReturnScope boost126 =null; + ParserRuleReturnScope ftsFieldGroupTest128 =null; + ParserRuleReturnScope boost129 =null; + + Object PLUS121_tree=null; + Object BAR124_tree=null; + Object MINUS127_tree=null; + RewriteRuleTokenStream stream_BAR=new RewriteRuleTokenStream(adaptor,"token BAR"); + RewriteRuleTokenStream stream_PLUS=new RewriteRuleTokenStream(adaptor,"token PLUS"); + RewriteRuleTokenStream stream_MINUS=new RewriteRuleTokenStream(adaptor,"token MINUS"); + RewriteRuleSubtreeStream stream_not=new RewriteRuleSubtreeStream(adaptor,"rule not"); + RewriteRuleSubtreeStream stream_ftsFieldGroupTest=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupTest"); + RewriteRuleSubtreeStream stream_boost=new RewriteRuleSubtreeStream(adaptor,"rule boost"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:641:9: ( ( not )=> not ftsFieldGroupTest ( boost )? -> ^( FIELD_NEGATION ftsFieldGroupTest ( boost )? ) | ftsFieldGroupTest ( boost )? -> ^( FIELD_DEFAULT ftsFieldGroupTest ( boost )? ) | PLUS ftsFieldGroupTest ( boost )? -> ^( FIELD_MANDATORY ftsFieldGroupTest ( boost )? ) | BAR ftsFieldGroupTest ( boost )? -> ^( FIELD_OPTIONAL ftsFieldGroupTest ( boost )? ) | MINUS ftsFieldGroupTest ( boost )? -> ^( FIELD_EXCLUDE ftsFieldGroupTest ( boost )? ) ) + int alt53=5; + int LA53_0 = input.LA(1); + if ( (LA53_0==NOT) ) { + int LA53_1 = input.LA(2); + if ( (synpred23_FTS()) ) { + alt53=1; + } + else if ( (true) ) { + alt53=2; + } + + } + else if ( (LA53_0==COMMA||LA53_0==DATETIME||LA53_0==DECIMAL_INTEGER_LITERAL||LA53_0==DOT||LA53_0==EQUALS||LA53_0==FLOATING_POINT_LITERAL||(LA53_0 >= FTSPHRASE && LA53_0 <= FTSWORD)||LA53_0==ID||(LA53_0 >= LPAREN && LA53_0 <= LT)||LA53_0==QUESTION_MARK||LA53_0==STAR||(LA53_0 >= TILDA && LA53_0 <= TO)||LA53_0==URI) ) { + alt53=2; + } + else if ( (LA53_0==EXCLAMATION) && (synpred23_FTS())) { + alt53=1; + } + else if ( (LA53_0==PLUS) ) { + alt53=3; + } + else if ( (LA53_0==BAR) ) { + alt53=4; + } + else if ( (LA53_0==MINUS) ) { + alt53=5; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 53, 0, input); + throw nvae; + } + + switch (alt53) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:642:9: ( not )=> not ftsFieldGroupTest ( boost )? + { + pushFollow(FOLLOW_not_in_ftsFieldGroupPrefixed4379); + not116=not(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_not.add(not116.getTree()); + pushFollow(FOLLOW_ftsFieldGroupTest_in_ftsFieldGroupPrefixed4381); + ftsFieldGroupTest117=ftsFieldGroupTest(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupTest.add(ftsFieldGroupTest117.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:642:40: ( boost )? + int alt48=2; + int LA48_0 = input.LA(1); + if ( (LA48_0==CARAT) ) { + alt48=1; + } + switch (alt48) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:642:40: boost + { + pushFollow(FOLLOW_boost_in_ftsFieldGroupPrefixed4383); + boost118=boost(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_boost.add(boost118.getTree()); + } + break; + + } + + // AST REWRITE + // elements: ftsFieldGroupTest, boost + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 643:17: -> ^( FIELD_NEGATION ftsFieldGroupTest ( boost )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:644:25: ^( FIELD_NEGATION ftsFieldGroupTest ( boost )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FIELD_NEGATION, "FIELD_NEGATION"), root_1); + adaptor.addChild(root_1, stream_ftsFieldGroupTest.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:644:60: ( boost )? + if ( stream_boost.hasNext() ) { + adaptor.addChild(root_1, stream_boost.nextTree()); + } + stream_boost.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:645:11: ftsFieldGroupTest ( boost )? + { + pushFollow(FOLLOW_ftsFieldGroupTest_in_ftsFieldGroupPrefixed4447); + ftsFieldGroupTest119=ftsFieldGroupTest(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupTest.add(ftsFieldGroupTest119.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:645:29: ( boost )? + int alt49=2; + int LA49_0 = input.LA(1); + if ( (LA49_0==CARAT) ) { + alt49=1; + } + switch (alt49) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:645:29: boost + { + pushFollow(FOLLOW_boost_in_ftsFieldGroupPrefixed4449); + boost120=boost(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_boost.add(boost120.getTree()); + } + break; + + } + + // AST REWRITE + // elements: boost, ftsFieldGroupTest + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 646:17: -> ^( FIELD_DEFAULT ftsFieldGroupTest ( boost )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:647:25: ^( FIELD_DEFAULT ftsFieldGroupTest ( boost )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FIELD_DEFAULT, "FIELD_DEFAULT"), root_1); + adaptor.addChild(root_1, stream_ftsFieldGroupTest.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:647:59: ( boost )? + if ( stream_boost.hasNext() ) { + adaptor.addChild(root_1, stream_boost.nextTree()); + } + stream_boost.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:648:11: PLUS ftsFieldGroupTest ( boost )? + { + PLUS121=(Token)match(input,PLUS,FOLLOW_PLUS_in_ftsFieldGroupPrefixed4513); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_PLUS.add(PLUS121); + + pushFollow(FOLLOW_ftsFieldGroupTest_in_ftsFieldGroupPrefixed4515); + ftsFieldGroupTest122=ftsFieldGroupTest(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupTest.add(ftsFieldGroupTest122.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:648:34: ( boost )? + int alt50=2; + int LA50_0 = input.LA(1); + if ( (LA50_0==CARAT) ) { + alt50=1; + } + switch (alt50) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:648:34: boost + { + pushFollow(FOLLOW_boost_in_ftsFieldGroupPrefixed4517); + boost123=boost(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_boost.add(boost123.getTree()); + } + break; + + } + + // AST REWRITE + // elements: boost, ftsFieldGroupTest + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 649:17: -> ^( FIELD_MANDATORY ftsFieldGroupTest ( boost )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:650:25: ^( FIELD_MANDATORY ftsFieldGroupTest ( boost )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FIELD_MANDATORY, "FIELD_MANDATORY"), root_1); + adaptor.addChild(root_1, stream_ftsFieldGroupTest.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:650:61: ( boost )? + if ( stream_boost.hasNext() ) { + adaptor.addChild(root_1, stream_boost.nextTree()); + } + stream_boost.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:651:11: BAR ftsFieldGroupTest ( boost )? + { + BAR124=(Token)match(input,BAR,FOLLOW_BAR_in_ftsFieldGroupPrefixed4581); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_BAR.add(BAR124); + + pushFollow(FOLLOW_ftsFieldGroupTest_in_ftsFieldGroupPrefixed4583); + ftsFieldGroupTest125=ftsFieldGroupTest(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupTest.add(ftsFieldGroupTest125.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:651:33: ( boost )? + int alt51=2; + int LA51_0 = input.LA(1); + if ( (LA51_0==CARAT) ) { + alt51=1; + } + switch (alt51) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:651:33: boost + { + pushFollow(FOLLOW_boost_in_ftsFieldGroupPrefixed4585); + boost126=boost(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_boost.add(boost126.getTree()); + } + break; + + } + + // AST REWRITE + // elements: boost, ftsFieldGroupTest + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 652:17: -> ^( FIELD_OPTIONAL ftsFieldGroupTest ( boost )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:653:25: ^( FIELD_OPTIONAL ftsFieldGroupTest ( boost )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FIELD_OPTIONAL, "FIELD_OPTIONAL"), root_1); + adaptor.addChild(root_1, stream_ftsFieldGroupTest.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:653:60: ( boost )? + if ( stream_boost.hasNext() ) { + adaptor.addChild(root_1, stream_boost.nextTree()); + } + stream_boost.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:654:11: MINUS ftsFieldGroupTest ( boost )? + { + MINUS127=(Token)match(input,MINUS,FOLLOW_MINUS_in_ftsFieldGroupPrefixed4649); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_MINUS.add(MINUS127); + + pushFollow(FOLLOW_ftsFieldGroupTest_in_ftsFieldGroupPrefixed4651); + ftsFieldGroupTest128=ftsFieldGroupTest(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupTest.add(ftsFieldGroupTest128.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:654:35: ( boost )? + int alt52=2; + int LA52_0 = input.LA(1); + if ( (LA52_0==CARAT) ) { + alt52=1; + } + switch (alt52) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:654:35: boost + { + pushFollow(FOLLOW_boost_in_ftsFieldGroupPrefixed4653); + boost129=boost(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_boost.add(boost129.getTree()); + } + break; + + } + + // AST REWRITE + // elements: boost, ftsFieldGroupTest + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 655:17: -> ^( FIELD_EXCLUDE ftsFieldGroupTest ( boost )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:656:25: ^( FIELD_EXCLUDE ftsFieldGroupTest ( boost )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FIELD_EXCLUDE, "FIELD_EXCLUDE"), root_1); + adaptor.addChild(root_1, stream_ftsFieldGroupTest.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:656:59: ( boost )? + if ( stream_boost.hasNext() ) { + adaptor.addChild(root_1, stream_boost.nextTree()); + } + stream_boost.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupPrefixed" + + + public static class ftsFieldGroupTest_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupTest" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:659:1: ftsFieldGroupTest : ( ( ftsFieldGroupProximity )=> ftsFieldGroupProximity -> ^( FG_PROXIMITY ftsFieldGroupProximity ) | ( ftsFieldGroupTerm )=> ftsFieldGroupTerm ( ( fuzzy )=> fuzzy )? -> ^( FG_TERM ftsFieldGroupTerm ( fuzzy )? ) | ( ftsFieldGroupExactTerm )=> ftsFieldGroupExactTerm ( ( fuzzy )=> fuzzy )? -> ^( FG_EXACT_TERM ftsFieldGroupExactTerm ( fuzzy )? ) | ( ftsFieldGroupPhrase )=> ftsFieldGroupPhrase ( ( slop )=> slop )? -> ^( FG_PHRASE ftsFieldGroupPhrase ( slop )? ) | ( ftsFieldGroupExactPhrase )=> ftsFieldGroupExactPhrase ( ( slop )=> slop )? -> ^( FG_EXACT_PHRASE ftsFieldGroupExactPhrase ( slop )? ) | ( ftsFieldGroupTokenisedPhrase )=> ftsFieldGroupTokenisedPhrase ( ( slop )=> slop )? -> ^( FG_PHRASE ftsFieldGroupTokenisedPhrase ( slop )? ) | ( ftsFieldGroupSynonym )=> ftsFieldGroupSynonym ( ( fuzzy )=> fuzzy )? -> ^( FG_SYNONYM ftsFieldGroupSynonym ( fuzzy )? ) | ( ftsFieldGroupRange )=> ftsFieldGroupRange -> ^( FG_RANGE ftsFieldGroupRange ) | LPAREN ftsFieldGroupDisjunction RPAREN -> ftsFieldGroupDisjunction ); + public final FTSParser.ftsFieldGroupTest_return ftsFieldGroupTest() throws RecognitionException { + FTSParser.ftsFieldGroupTest_return retval = new FTSParser.ftsFieldGroupTest_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token LPAREN144=null; + Token RPAREN146=null; + ParserRuleReturnScope ftsFieldGroupProximity130 =null; + ParserRuleReturnScope ftsFieldGroupTerm131 =null; + ParserRuleReturnScope fuzzy132 =null; + ParserRuleReturnScope ftsFieldGroupExactTerm133 =null; + ParserRuleReturnScope fuzzy134 =null; + ParserRuleReturnScope ftsFieldGroupPhrase135 =null; + ParserRuleReturnScope slop136 =null; + ParserRuleReturnScope ftsFieldGroupExactPhrase137 =null; + ParserRuleReturnScope slop138 =null; + ParserRuleReturnScope ftsFieldGroupTokenisedPhrase139 =null; + ParserRuleReturnScope slop140 =null; + ParserRuleReturnScope ftsFieldGroupSynonym141 =null; + ParserRuleReturnScope fuzzy142 =null; + ParserRuleReturnScope ftsFieldGroupRange143 =null; + ParserRuleReturnScope ftsFieldGroupDisjunction145 =null; + + Object LPAREN144_tree=null; + Object RPAREN146_tree=null; + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + RewriteRuleSubtreeStream stream_ftsFieldGroupSynonym=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupSynonym"); + RewriteRuleSubtreeStream stream_ftsFieldGroupRange=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupRange"); + RewriteRuleSubtreeStream stream_ftsFieldGroupProximity=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupProximity"); + RewriteRuleSubtreeStream stream_ftsFieldGroupDisjunction=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupDisjunction"); + RewriteRuleSubtreeStream stream_ftsFieldGroupExactTerm=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupExactTerm"); + RewriteRuleSubtreeStream stream_ftsFieldGroupExactPhrase=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupExactPhrase"); + RewriteRuleSubtreeStream stream_ftsFieldGroupTokenisedPhrase=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupTokenisedPhrase"); + RewriteRuleSubtreeStream stream_fuzzy=new RewriteRuleSubtreeStream(adaptor,"rule fuzzy"); + RewriteRuleSubtreeStream stream_ftsFieldGroupPhrase=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupPhrase"); + RewriteRuleSubtreeStream stream_ftsFieldGroupTerm=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupTerm"); + RewriteRuleSubtreeStream stream_slop=new RewriteRuleSubtreeStream(adaptor,"rule slop"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:660:9: ( ( ftsFieldGroupProximity )=> ftsFieldGroupProximity -> ^( FG_PROXIMITY ftsFieldGroupProximity ) | ( ftsFieldGroupTerm )=> ftsFieldGroupTerm ( ( fuzzy )=> fuzzy )? -> ^( FG_TERM ftsFieldGroupTerm ( fuzzy )? ) | ( ftsFieldGroupExactTerm )=> ftsFieldGroupExactTerm ( ( fuzzy )=> fuzzy )? -> ^( FG_EXACT_TERM ftsFieldGroupExactTerm ( fuzzy )? ) | ( ftsFieldGroupPhrase )=> ftsFieldGroupPhrase ( ( slop )=> slop )? -> ^( FG_PHRASE ftsFieldGroupPhrase ( slop )? ) | ( ftsFieldGroupExactPhrase )=> ftsFieldGroupExactPhrase ( ( slop )=> slop )? -> ^( FG_EXACT_PHRASE ftsFieldGroupExactPhrase ( slop )? ) | ( ftsFieldGroupTokenisedPhrase )=> ftsFieldGroupTokenisedPhrase ( ( slop )=> slop )? -> ^( FG_PHRASE ftsFieldGroupTokenisedPhrase ( slop )? ) | ( ftsFieldGroupSynonym )=> ftsFieldGroupSynonym ( ( fuzzy )=> fuzzy )? -> ^( FG_SYNONYM ftsFieldGroupSynonym ( fuzzy )? ) | ( ftsFieldGroupRange )=> ftsFieldGroupRange -> ^( FG_RANGE ftsFieldGroupRange ) | LPAREN ftsFieldGroupDisjunction RPAREN -> ftsFieldGroupDisjunction ) + int alt60=9; + alt60 = dfa60.predict(input); + switch (alt60) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:661:9: ( ftsFieldGroupProximity )=> ftsFieldGroupProximity + { + pushFollow(FOLLOW_ftsFieldGroupProximity_in_ftsFieldGroupTest4744); + ftsFieldGroupProximity130=ftsFieldGroupProximity(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupProximity.add(ftsFieldGroupProximity130.getTree()); + // AST REWRITE + // elements: ftsFieldGroupProximity + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 662:17: -> ^( FG_PROXIMITY ftsFieldGroupProximity ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:663:25: ^( FG_PROXIMITY ftsFieldGroupProximity ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FG_PROXIMITY, "FG_PROXIMITY"), root_1); + adaptor.addChild(root_1, stream_ftsFieldGroupProximity.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:664:11: ( ftsFieldGroupTerm )=> ftsFieldGroupTerm ( ( fuzzy )=> fuzzy )? + { + pushFollow(FOLLOW_ftsFieldGroupTerm_in_ftsFieldGroupTest4810); + ftsFieldGroupTerm131=ftsFieldGroupTerm(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupTerm.add(ftsFieldGroupTerm131.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:664:52: ( ( fuzzy )=> fuzzy )? + int alt54=2; + int LA54_0 = input.LA(1); + if ( (LA54_0==TILDA) ) { + int LA54_1 = input.LA(2); + if ( (LA54_1==DECIMAL_INTEGER_LITERAL) ) { + int LA54_3 = input.LA(3); + if ( (synpred26_FTS()) ) { + alt54=1; + } + } + else if ( (LA54_1==FLOATING_POINT_LITERAL) ) { + int LA54_4 = input.LA(3); + if ( (synpred26_FTS()) ) { + alt54=1; + } + } + } + switch (alt54) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:664:54: ( fuzzy )=> fuzzy + { + pushFollow(FOLLOW_fuzzy_in_ftsFieldGroupTest4820); + fuzzy132=fuzzy(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fuzzy.add(fuzzy132.getTree()); + } + break; + + } + + // AST REWRITE + // elements: ftsFieldGroupTerm, fuzzy + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 665:17: -> ^( FG_TERM ftsFieldGroupTerm ( fuzzy )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:666:25: ^( FG_TERM ftsFieldGroupTerm ( fuzzy )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FG_TERM, "FG_TERM"), root_1); + adaptor.addChild(root_1, stream_ftsFieldGroupTerm.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:666:53: ( fuzzy )? + if ( stream_fuzzy.hasNext() ) { + adaptor.addChild(root_1, stream_fuzzy.nextTree()); + } + stream_fuzzy.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:667:11: ( ftsFieldGroupExactTerm )=> ftsFieldGroupExactTerm ( ( fuzzy )=> fuzzy )? + { + pushFollow(FOLLOW_ftsFieldGroupExactTerm_in_ftsFieldGroupTest4891); + ftsFieldGroupExactTerm133=ftsFieldGroupExactTerm(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupExactTerm.add(ftsFieldGroupExactTerm133.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:667:62: ( ( fuzzy )=> fuzzy )? + int alt55=2; + int LA55_0 = input.LA(1); + if ( (LA55_0==TILDA) ) { + int LA55_1 = input.LA(2); + if ( (LA55_1==DECIMAL_INTEGER_LITERAL) ) { + int LA55_3 = input.LA(3); + if ( (synpred28_FTS()) ) { + alt55=1; + } + } + else if ( (LA55_1==FLOATING_POINT_LITERAL) ) { + int LA55_4 = input.LA(3); + if ( (synpred28_FTS()) ) { + alt55=1; + } + } + } + switch (alt55) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:667:64: ( fuzzy )=> fuzzy + { + pushFollow(FOLLOW_fuzzy_in_ftsFieldGroupTest4901); + fuzzy134=fuzzy(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fuzzy.add(fuzzy134.getTree()); + } + break; + + } + + // AST REWRITE + // elements: ftsFieldGroupExactTerm, fuzzy + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 668:17: -> ^( FG_EXACT_TERM ftsFieldGroupExactTerm ( fuzzy )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:669:25: ^( FG_EXACT_TERM ftsFieldGroupExactTerm ( fuzzy )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FG_EXACT_TERM, "FG_EXACT_TERM"), root_1); + adaptor.addChild(root_1, stream_ftsFieldGroupExactTerm.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:669:64: ( fuzzy )? + if ( stream_fuzzy.hasNext() ) { + adaptor.addChild(root_1, stream_fuzzy.nextTree()); + } + stream_fuzzy.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:670:11: ( ftsFieldGroupPhrase )=> ftsFieldGroupPhrase ( ( slop )=> slop )? + { + pushFollow(FOLLOW_ftsFieldGroupPhrase_in_ftsFieldGroupTest4972); + ftsFieldGroupPhrase135=ftsFieldGroupPhrase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupPhrase.add(ftsFieldGroupPhrase135.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:670:56: ( ( slop )=> slop )? + int alt56=2; + int LA56_0 = input.LA(1); + if ( (LA56_0==TILDA) ) { + int LA56_1 = input.LA(2); + if ( (LA56_1==DECIMAL_INTEGER_LITERAL) ) { + int LA56_3 = input.LA(3); + if ( (synpred30_FTS()) ) { + alt56=1; + } + } + } + switch (alt56) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:670:58: ( slop )=> slop + { + pushFollow(FOLLOW_slop_in_ftsFieldGroupTest4982); + slop136=slop(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_slop.add(slop136.getTree()); + } + break; + + } + + // AST REWRITE + // elements: slop, ftsFieldGroupPhrase + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 671:17: -> ^( FG_PHRASE ftsFieldGroupPhrase ( slop )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:672:25: ^( FG_PHRASE ftsFieldGroupPhrase ( slop )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FG_PHRASE, "FG_PHRASE"), root_1); + adaptor.addChild(root_1, stream_ftsFieldGroupPhrase.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:672:57: ( slop )? + if ( stream_slop.hasNext() ) { + adaptor.addChild(root_1, stream_slop.nextTree()); + } + stream_slop.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:673:11: ( ftsFieldGroupExactPhrase )=> ftsFieldGroupExactPhrase ( ( slop )=> slop )? + { + pushFollow(FOLLOW_ftsFieldGroupExactPhrase_in_ftsFieldGroupTest5053); + ftsFieldGroupExactPhrase137=ftsFieldGroupExactPhrase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupExactPhrase.add(ftsFieldGroupExactPhrase137.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:673:66: ( ( slop )=> slop )? + int alt57=2; + int LA57_0 = input.LA(1); + if ( (LA57_0==TILDA) ) { + int LA57_1 = input.LA(2); + if ( (LA57_1==DECIMAL_INTEGER_LITERAL) ) { + int LA57_3 = input.LA(3); + if ( (synpred32_FTS()) ) { + alt57=1; + } + } + } + switch (alt57) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:673:68: ( slop )=> slop + { + pushFollow(FOLLOW_slop_in_ftsFieldGroupTest5063); + slop138=slop(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_slop.add(slop138.getTree()); + } + break; + + } + + // AST REWRITE + // elements: ftsFieldGroupExactPhrase, slop + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 674:17: -> ^( FG_EXACT_PHRASE ftsFieldGroupExactPhrase ( slop )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:675:25: ^( FG_EXACT_PHRASE ftsFieldGroupExactPhrase ( slop )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FG_EXACT_PHRASE, "FG_EXACT_PHRASE"), root_1); + adaptor.addChild(root_1, stream_ftsFieldGroupExactPhrase.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:675:68: ( slop )? + if ( stream_slop.hasNext() ) { + adaptor.addChild(root_1, stream_slop.nextTree()); + } + stream_slop.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 6 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:676:11: ( ftsFieldGroupTokenisedPhrase )=> ftsFieldGroupTokenisedPhrase ( ( slop )=> slop )? + { + pushFollow(FOLLOW_ftsFieldGroupTokenisedPhrase_in_ftsFieldGroupTest5134); + ftsFieldGroupTokenisedPhrase139=ftsFieldGroupTokenisedPhrase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupTokenisedPhrase.add(ftsFieldGroupTokenisedPhrase139.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:676:74: ( ( slop )=> slop )? + int alt58=2; + int LA58_0 = input.LA(1); + if ( (LA58_0==TILDA) ) { + int LA58_1 = input.LA(2); + if ( (LA58_1==DECIMAL_INTEGER_LITERAL) ) { + int LA58_3 = input.LA(3); + if ( (synpred34_FTS()) ) { + alt58=1; + } + } + } + switch (alt58) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:676:76: ( slop )=> slop + { + pushFollow(FOLLOW_slop_in_ftsFieldGroupTest5144); + slop140=slop(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_slop.add(slop140.getTree()); + } + break; + + } + + // AST REWRITE + // elements: slop, ftsFieldGroupTokenisedPhrase + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 677:17: -> ^( FG_PHRASE ftsFieldGroupTokenisedPhrase ( slop )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:678:25: ^( FG_PHRASE ftsFieldGroupTokenisedPhrase ( slop )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FG_PHRASE, "FG_PHRASE"), root_1); + adaptor.addChild(root_1, stream_ftsFieldGroupTokenisedPhrase.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:678:66: ( slop )? + if ( stream_slop.hasNext() ) { + adaptor.addChild(root_1, stream_slop.nextTree()); + } + stream_slop.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 7 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:679:11: ( ftsFieldGroupSynonym )=> ftsFieldGroupSynonym ( ( fuzzy )=> fuzzy )? + { + pushFollow(FOLLOW_ftsFieldGroupSynonym_in_ftsFieldGroupTest5215); + ftsFieldGroupSynonym141=ftsFieldGroupSynonym(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupSynonym.add(ftsFieldGroupSynonym141.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:679:58: ( ( fuzzy )=> fuzzy )? + int alt59=2; + int LA59_0 = input.LA(1); + if ( (LA59_0==TILDA) ) { + int LA59_1 = input.LA(2); + if ( (LA59_1==DECIMAL_INTEGER_LITERAL) ) { + int LA59_3 = input.LA(3); + if ( (synpred36_FTS()) ) { + alt59=1; + } + } + else if ( (LA59_1==FLOATING_POINT_LITERAL) ) { + int LA59_4 = input.LA(3); + if ( (synpred36_FTS()) ) { + alt59=1; + } + } + } + switch (alt59) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:679:60: ( fuzzy )=> fuzzy + { + pushFollow(FOLLOW_fuzzy_in_ftsFieldGroupTest5225); + fuzzy142=fuzzy(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_fuzzy.add(fuzzy142.getTree()); + } + break; + + } + + // AST REWRITE + // elements: fuzzy, ftsFieldGroupSynonym + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 680:17: -> ^( FG_SYNONYM ftsFieldGroupSynonym ( fuzzy )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:681:25: ^( FG_SYNONYM ftsFieldGroupSynonym ( fuzzy )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FG_SYNONYM, "FG_SYNONYM"), root_1); + adaptor.addChild(root_1, stream_ftsFieldGroupSynonym.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:681:59: ( fuzzy )? + if ( stream_fuzzy.hasNext() ) { + adaptor.addChild(root_1, stream_fuzzy.nextTree()); + } + stream_fuzzy.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 8 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:682:11: ( ftsFieldGroupRange )=> ftsFieldGroupRange + { + pushFollow(FOLLOW_ftsFieldGroupRange_in_ftsFieldGroupTest5296); + ftsFieldGroupRange143=ftsFieldGroupRange(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupRange.add(ftsFieldGroupRange143.getTree()); + // AST REWRITE + // elements: ftsFieldGroupRange + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 683:17: -> ^( FG_RANGE ftsFieldGroupRange ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:684:25: ^( FG_RANGE ftsFieldGroupRange ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FG_RANGE, "FG_RANGE"), root_1); + adaptor.addChild(root_1, stream_ftsFieldGroupRange.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + break; + case 9 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:685:11: LPAREN ftsFieldGroupDisjunction RPAREN + { + LPAREN144=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_ftsFieldGroupTest5356); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(LPAREN144); + + pushFollow(FOLLOW_ftsFieldGroupDisjunction_in_ftsFieldGroupTest5358); + ftsFieldGroupDisjunction145=ftsFieldGroupDisjunction(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupDisjunction.add(ftsFieldGroupDisjunction145.getTree()); + RPAREN146=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_ftsFieldGroupTest5360); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(RPAREN146); + + // AST REWRITE + // elements: ftsFieldGroupDisjunction + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 686:17: -> ftsFieldGroupDisjunction + { + adaptor.addChild(root_0, stream_ftsFieldGroupDisjunction.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupTest" + + + public static class ftsFieldGroupTerm_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupTerm" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:689:1: ftsFieldGroupTerm : ftsWord ; + public final FTSParser.ftsFieldGroupTerm_return ftsFieldGroupTerm() throws RecognitionException { + FTSParser.ftsFieldGroupTerm_return retval = new FTSParser.ftsFieldGroupTerm_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope ftsWord147 =null; + + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:690:9: ( ftsWord ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:691:9: ftsWord + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_ftsWord_in_ftsFieldGroupTerm5413); + ftsWord147=ftsWord(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWord147.getTree()); + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupTerm" + + + public static class ftsFieldGroupExactTerm_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupExactTerm" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:694:1: ftsFieldGroupExactTerm : EQUALS ftsFieldGroupTerm -> ftsFieldGroupTerm ; + public final FTSParser.ftsFieldGroupExactTerm_return ftsFieldGroupExactTerm() throws RecognitionException { + FTSParser.ftsFieldGroupExactTerm_return retval = new FTSParser.ftsFieldGroupExactTerm_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token EQUALS148=null; + ParserRuleReturnScope ftsFieldGroupTerm149 =null; + + Object EQUALS148_tree=null; + RewriteRuleTokenStream stream_EQUALS=new RewriteRuleTokenStream(adaptor,"token EQUALS"); + RewriteRuleSubtreeStream stream_ftsFieldGroupTerm=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupTerm"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:695:9: ( EQUALS ftsFieldGroupTerm -> ftsFieldGroupTerm ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:696:9: EQUALS ftsFieldGroupTerm + { + EQUALS148=(Token)match(input,EQUALS,FOLLOW_EQUALS_in_ftsFieldGroupExactTerm5446); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_EQUALS.add(EQUALS148); + + pushFollow(FOLLOW_ftsFieldGroupTerm_in_ftsFieldGroupExactTerm5448); + ftsFieldGroupTerm149=ftsFieldGroupTerm(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupTerm.add(ftsFieldGroupTerm149.getTree()); + // AST REWRITE + // elements: ftsFieldGroupTerm + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 697:17: -> ftsFieldGroupTerm + { + adaptor.addChild(root_0, stream_ftsFieldGroupTerm.nextTree()); + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupExactTerm" + + + public static class ftsFieldGroupPhrase_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupPhrase" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:700:1: ftsFieldGroupPhrase : FTSPHRASE ; + public final FTSParser.ftsFieldGroupPhrase_return ftsFieldGroupPhrase() throws RecognitionException { + FTSParser.ftsFieldGroupPhrase_return retval = new FTSParser.ftsFieldGroupPhrase_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token FTSPHRASE150=null; + + Object FTSPHRASE150_tree=null; + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:701:9: ( FTSPHRASE ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:702:9: FTSPHRASE + { + root_0 = (Object)adaptor.nil(); + + + FTSPHRASE150=(Token)match(input,FTSPHRASE,FOLLOW_FTSPHRASE_in_ftsFieldGroupPhrase5501); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FTSPHRASE150_tree = (Object)adaptor.create(FTSPHRASE150); + adaptor.addChild(root_0, FTSPHRASE150_tree); + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupPhrase" + + + public static class ftsFieldGroupExactPhrase_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupExactPhrase" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:705:1: ftsFieldGroupExactPhrase : EQUALS ftsFieldGroupExactPhrase -> ftsFieldGroupExactPhrase ; + public final FTSParser.ftsFieldGroupExactPhrase_return ftsFieldGroupExactPhrase() throws RecognitionException { + FTSParser.ftsFieldGroupExactPhrase_return retval = new FTSParser.ftsFieldGroupExactPhrase_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token EQUALS151=null; + ParserRuleReturnScope ftsFieldGroupExactPhrase152 =null; + + Object EQUALS151_tree=null; + RewriteRuleTokenStream stream_EQUALS=new RewriteRuleTokenStream(adaptor,"token EQUALS"); + RewriteRuleSubtreeStream stream_ftsFieldGroupExactPhrase=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupExactPhrase"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:706:9: ( EQUALS ftsFieldGroupExactPhrase -> ftsFieldGroupExactPhrase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:707:9: EQUALS ftsFieldGroupExactPhrase + { + EQUALS151=(Token)match(input,EQUALS,FOLLOW_EQUALS_in_ftsFieldGroupExactPhrase5542); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_EQUALS.add(EQUALS151); + + pushFollow(FOLLOW_ftsFieldGroupExactPhrase_in_ftsFieldGroupExactPhrase5544); + ftsFieldGroupExactPhrase152=ftsFieldGroupExactPhrase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupExactPhrase.add(ftsFieldGroupExactPhrase152.getTree()); + // AST REWRITE + // elements: ftsFieldGroupExactPhrase + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 708:17: -> ftsFieldGroupExactPhrase + { + adaptor.addChild(root_0, stream_ftsFieldGroupExactPhrase.nextTree()); + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupExactPhrase" + + + public static class ftsFieldGroupTokenisedPhrase_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupTokenisedPhrase" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:711:1: ftsFieldGroupTokenisedPhrase : TILDA ftsFieldGroupExactPhrase -> ftsFieldGroupExactPhrase ; + public final FTSParser.ftsFieldGroupTokenisedPhrase_return ftsFieldGroupTokenisedPhrase() throws RecognitionException { + FTSParser.ftsFieldGroupTokenisedPhrase_return retval = new FTSParser.ftsFieldGroupTokenisedPhrase_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token TILDA153=null; + ParserRuleReturnScope ftsFieldGroupExactPhrase154 =null; + + Object TILDA153_tree=null; + RewriteRuleTokenStream stream_TILDA=new RewriteRuleTokenStream(adaptor,"token TILDA"); + RewriteRuleSubtreeStream stream_ftsFieldGroupExactPhrase=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupExactPhrase"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:712:9: ( TILDA ftsFieldGroupExactPhrase -> ftsFieldGroupExactPhrase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:713:9: TILDA ftsFieldGroupExactPhrase + { + TILDA153=(Token)match(input,TILDA,FOLLOW_TILDA_in_ftsFieldGroupTokenisedPhrase5605); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_TILDA.add(TILDA153); + + pushFollow(FOLLOW_ftsFieldGroupExactPhrase_in_ftsFieldGroupTokenisedPhrase5607); + ftsFieldGroupExactPhrase154=ftsFieldGroupExactPhrase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupExactPhrase.add(ftsFieldGroupExactPhrase154.getTree()); + // AST REWRITE + // elements: ftsFieldGroupExactPhrase + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 714:17: -> ftsFieldGroupExactPhrase + { + adaptor.addChild(root_0, stream_ftsFieldGroupExactPhrase.nextTree()); + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupTokenisedPhrase" + + + public static class ftsFieldGroupSynonym_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupSynonym" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:717:1: ftsFieldGroupSynonym : TILDA ftsFieldGroupTerm -> ftsFieldGroupTerm ; + public final FTSParser.ftsFieldGroupSynonym_return ftsFieldGroupSynonym() throws RecognitionException { + FTSParser.ftsFieldGroupSynonym_return retval = new FTSParser.ftsFieldGroupSynonym_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token TILDA155=null; + ParserRuleReturnScope ftsFieldGroupTerm156 =null; + + Object TILDA155_tree=null; + RewriteRuleTokenStream stream_TILDA=new RewriteRuleTokenStream(adaptor,"token TILDA"); + RewriteRuleSubtreeStream stream_ftsFieldGroupTerm=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupTerm"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:718:9: ( TILDA ftsFieldGroupTerm -> ftsFieldGroupTerm ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:719:9: TILDA ftsFieldGroupTerm + { + TILDA155=(Token)match(input,TILDA,FOLLOW_TILDA_in_ftsFieldGroupSynonym5660); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_TILDA.add(TILDA155); + + pushFollow(FOLLOW_ftsFieldGroupTerm_in_ftsFieldGroupSynonym5662); + ftsFieldGroupTerm156=ftsFieldGroupTerm(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupTerm.add(ftsFieldGroupTerm156.getTree()); + // AST REWRITE + // elements: ftsFieldGroupTerm + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 720:17: -> ftsFieldGroupTerm + { + adaptor.addChild(root_0, stream_ftsFieldGroupTerm.nextTree()); + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupSynonym" + + + public static class ftsFieldGroupProximity_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupProximity" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:723:1: ftsFieldGroupProximity : ftsFieldGroupProximityTerm ( ( proximityGroup )=> proximityGroup ftsFieldGroupProximityTerm )+ -> ftsFieldGroupProximityTerm ( proximityGroup ftsFieldGroupProximityTerm )+ ; + public final FTSParser.ftsFieldGroupProximity_return ftsFieldGroupProximity() throws RecognitionException { + FTSParser.ftsFieldGroupProximity_return retval = new FTSParser.ftsFieldGroupProximity_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + ParserRuleReturnScope ftsFieldGroupProximityTerm157 =null; + ParserRuleReturnScope proximityGroup158 =null; + ParserRuleReturnScope ftsFieldGroupProximityTerm159 =null; + + RewriteRuleSubtreeStream stream_proximityGroup=new RewriteRuleSubtreeStream(adaptor,"rule proximityGroup"); + RewriteRuleSubtreeStream stream_ftsFieldGroupProximityTerm=new RewriteRuleSubtreeStream(adaptor,"rule ftsFieldGroupProximityTerm"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:724:9: ( ftsFieldGroupProximityTerm ( ( proximityGroup )=> proximityGroup ftsFieldGroupProximityTerm )+ -> ftsFieldGroupProximityTerm ( proximityGroup ftsFieldGroupProximityTerm )+ ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:725:9: ftsFieldGroupProximityTerm ( ( proximityGroup )=> proximityGroup ftsFieldGroupProximityTerm )+ + { + pushFollow(FOLLOW_ftsFieldGroupProximityTerm_in_ftsFieldGroupProximity5715); + ftsFieldGroupProximityTerm157=ftsFieldGroupProximityTerm(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupProximityTerm.add(ftsFieldGroupProximityTerm157.getTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:725:36: ( ( proximityGroup )=> proximityGroup ftsFieldGroupProximityTerm )+ + int cnt61=0; + loop61: + while (true) { + int alt61=2; + int LA61_0 = input.LA(1); + if ( (LA61_0==STAR) ) { + switch ( input.LA(2) ) { + case STAR: + { + int LA61_3 = input.LA(3); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case NOT: + { + int LA61_4 = input.LA(3); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case ID: + { + int LA61_5 = input.LA(3); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case FTSWORD: + { + int LA61_6 = input.LA(3); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case FTSPRE: + { + int LA61_7 = input.LA(3); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case FTSWILD: + { + int LA61_8 = input.LA(3); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case TO: + { + int LA61_9 = input.LA(3); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case DECIMAL_INTEGER_LITERAL: + { + int LA61_10 = input.LA(3); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case FLOATING_POINT_LITERAL: + { + int LA61_11 = input.LA(3); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case DATETIME: + { + int LA61_12 = input.LA(3); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case URI: + { + switch ( input.LA(3) ) { + case ID: + { + int LA61_16 = input.LA(4); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case TO: + { + int LA61_17 = input.LA(4); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case OR: + { + int LA61_18 = input.LA(4); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case AND: + { + int LA61_19 = input.LA(4); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case NOT: + { + int LA61_20 = input.LA(4); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + } + } + break; + case LPAREN: + { + int LA61_14 = input.LA(3); + if ( (LA61_14==DECIMAL_INTEGER_LITERAL) ) { + int LA61_21 = input.LA(4); + if ( (LA61_21==RPAREN) ) { + switch ( input.LA(5) ) { + case NOT: + { + int LA61_24 = input.LA(6); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case ID: + { + int LA61_25 = input.LA(6); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case FTSWORD: + { + int LA61_26 = input.LA(6); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case FTSPRE: + { + int LA61_27 = input.LA(6); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case FTSWILD: + { + int LA61_28 = input.LA(6); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case TO: + { + int LA61_29 = input.LA(6); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case DECIMAL_INTEGER_LITERAL: + { + int LA61_30 = input.LA(6); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case FLOATING_POINT_LITERAL: + { + int LA61_31 = input.LA(6); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case DATETIME: + { + int LA61_32 = input.LA(6); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case STAR: + { + int LA61_33 = input.LA(6); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case URI: + { + switch ( input.LA(6) ) { + case ID: + { + int LA61_16 = input.LA(7); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case TO: + { + int LA61_17 = input.LA(7); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case OR: + { + int LA61_18 = input.LA(7); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case AND: + { + int LA61_19 = input.LA(7); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + case NOT: + { + int LA61_20 = input.LA(7); + if ( (synpred38_FTS()) ) { + alt61=1; + } + + } + break; + } + } + break; + } + } + + } + else if ( (LA61_14==RPAREN) && (synpred38_FTS())) { + alt61=1; + } + + } + break; + } + } + + switch (alt61) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:725:38: ( proximityGroup )=> proximityGroup ftsFieldGroupProximityTerm + { + pushFollow(FOLLOW_proximityGroup_in_ftsFieldGroupProximity5725); + proximityGroup158=proximityGroup(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_proximityGroup.add(proximityGroup158.getTree()); + pushFollow(FOLLOW_ftsFieldGroupProximityTerm_in_ftsFieldGroupProximity5727); + ftsFieldGroupProximityTerm159=ftsFieldGroupProximityTerm(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsFieldGroupProximityTerm.add(ftsFieldGroupProximityTerm159.getTree()); + } + break; + + default : + if ( cnt61 >= 1 ) break loop61; + if (state.backtracking>0) {state.failed=true; return retval;} + EarlyExitException eee = new EarlyExitException(61, input); + throw eee; + } + cnt61++; + } + + // AST REWRITE + // elements: ftsFieldGroupProximityTerm, proximityGroup, ftsFieldGroupProximityTerm + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 726:17: -> ftsFieldGroupProximityTerm ( proximityGroup ftsFieldGroupProximityTerm )+ + { + adaptor.addChild(root_0, stream_ftsFieldGroupProximityTerm.nextTree()); + if ( !(stream_ftsFieldGroupProximityTerm.hasNext()||stream_proximityGroup.hasNext()) ) { + throw new RewriteEarlyExitException(); + } + while ( stream_ftsFieldGroupProximityTerm.hasNext()||stream_proximityGroup.hasNext() ) { + adaptor.addChild(root_0, stream_proximityGroup.nextTree()); + adaptor.addChild(root_0, stream_ftsFieldGroupProximityTerm.nextTree()); + } + stream_ftsFieldGroupProximityTerm.reset(); + stream_proximityGroup.reset(); + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupProximity" + + + public static class ftsFieldGroupProximityTerm_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupProximityTerm" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:729:1: ftsFieldGroupProximityTerm : ( ID | FTSWORD | FTSPRE | FTSWILD | NOT | TO | DECIMAL_INTEGER_LITERAL | FLOATING_POINT_LITERAL | DATETIME | STAR | URI identifier ); + public final FTSParser.ftsFieldGroupProximityTerm_return ftsFieldGroupProximityTerm() throws RecognitionException { + FTSParser.ftsFieldGroupProximityTerm_return retval = new FTSParser.ftsFieldGroupProximityTerm_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token ID160=null; + Token FTSWORD161=null; + Token FTSPRE162=null; + Token FTSWILD163=null; + Token NOT164=null; + Token TO165=null; + Token DECIMAL_INTEGER_LITERAL166=null; + Token FLOATING_POINT_LITERAL167=null; + Token DATETIME168=null; + Token STAR169=null; + Token URI170=null; + ParserRuleReturnScope identifier171 =null; + + Object ID160_tree=null; + Object FTSWORD161_tree=null; + Object FTSPRE162_tree=null; + Object FTSWILD163_tree=null; + Object NOT164_tree=null; + Object TO165_tree=null; + Object DECIMAL_INTEGER_LITERAL166_tree=null; + Object FLOATING_POINT_LITERAL167_tree=null; + Object DATETIME168_tree=null; + Object STAR169_tree=null; + Object URI170_tree=null; + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:730:9: ( ID | FTSWORD | FTSPRE | FTSWILD | NOT | TO | DECIMAL_INTEGER_LITERAL | FLOATING_POINT_LITERAL | DATETIME | STAR | URI identifier ) + int alt62=11; + switch ( input.LA(1) ) { + case ID: + { + alt62=1; + } + break; + case FTSWORD: + { + alt62=2; + } + break; + case FTSPRE: + { + alt62=3; + } + break; + case FTSWILD: + { + alt62=4; + } + break; + case NOT: + { + alt62=5; + } + break; + case TO: + { + alt62=6; + } + break; + case DECIMAL_INTEGER_LITERAL: + { + alt62=7; + } + break; + case FLOATING_POINT_LITERAL: + { + alt62=8; + } + break; + case DATETIME: + { + alt62=9; + } + break; + case STAR: + { + alt62=10; + } + break; + case URI: + { + alt62=11; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 62, 0, input); + throw nvae; + } + switch (alt62) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:731:11: ID + { + root_0 = (Object)adaptor.nil(); + + + ID160=(Token)match(input,ID,FOLLOW_ID_in_ftsFieldGroupProximityTerm5791); if (state.failed) return retval; + if ( state.backtracking==0 ) { + ID160_tree = (Object)adaptor.create(ID160); + adaptor.addChild(root_0, ID160_tree); + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:732:11: FTSWORD + { + root_0 = (Object)adaptor.nil(); + + + FTSWORD161=(Token)match(input,FTSWORD,FOLLOW_FTSWORD_in_ftsFieldGroupProximityTerm5803); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FTSWORD161_tree = (Object)adaptor.create(FTSWORD161); + adaptor.addChild(root_0, FTSWORD161_tree); + } + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:733:11: FTSPRE + { + root_0 = (Object)adaptor.nil(); + + + FTSPRE162=(Token)match(input,FTSPRE,FOLLOW_FTSPRE_in_ftsFieldGroupProximityTerm5815); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FTSPRE162_tree = (Object)adaptor.create(FTSPRE162); + adaptor.addChild(root_0, FTSPRE162_tree); + } + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:734:11: FTSWILD + { + root_0 = (Object)adaptor.nil(); + + + FTSWILD163=(Token)match(input,FTSWILD,FOLLOW_FTSWILD_in_ftsFieldGroupProximityTerm5827); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FTSWILD163_tree = (Object)adaptor.create(FTSWILD163); + adaptor.addChild(root_0, FTSWILD163_tree); + } + + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:735:11: NOT + { + root_0 = (Object)adaptor.nil(); + + + NOT164=(Token)match(input,NOT,FOLLOW_NOT_in_ftsFieldGroupProximityTerm5839); if (state.failed) return retval; + if ( state.backtracking==0 ) { + NOT164_tree = (Object)adaptor.create(NOT164); + adaptor.addChild(root_0, NOT164_tree); + } + + } + break; + case 6 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:736:11: TO + { + root_0 = (Object)adaptor.nil(); + + + TO165=(Token)match(input,TO,FOLLOW_TO_in_ftsFieldGroupProximityTerm5851); if (state.failed) return retval; + if ( state.backtracking==0 ) { + TO165_tree = (Object)adaptor.create(TO165); + adaptor.addChild(root_0, TO165_tree); + } + + } + break; + case 7 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:737:11: DECIMAL_INTEGER_LITERAL + { + root_0 = (Object)adaptor.nil(); + + + DECIMAL_INTEGER_LITERAL166=(Token)match(input,DECIMAL_INTEGER_LITERAL,FOLLOW_DECIMAL_INTEGER_LITERAL_in_ftsFieldGroupProximityTerm5863); if (state.failed) return retval; + if ( state.backtracking==0 ) { + DECIMAL_INTEGER_LITERAL166_tree = (Object)adaptor.create(DECIMAL_INTEGER_LITERAL166); + adaptor.addChild(root_0, DECIMAL_INTEGER_LITERAL166_tree); + } + + } + break; + case 8 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:738:11: FLOATING_POINT_LITERAL + { + root_0 = (Object)adaptor.nil(); + + + FLOATING_POINT_LITERAL167=(Token)match(input,FLOATING_POINT_LITERAL,FOLLOW_FLOATING_POINT_LITERAL_in_ftsFieldGroupProximityTerm5875); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FLOATING_POINT_LITERAL167_tree = (Object)adaptor.create(FLOATING_POINT_LITERAL167); + adaptor.addChild(root_0, FLOATING_POINT_LITERAL167_tree); + } + + } + break; + case 9 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:739:11: DATETIME + { + root_0 = (Object)adaptor.nil(); + + + DATETIME168=(Token)match(input,DATETIME,FOLLOW_DATETIME_in_ftsFieldGroupProximityTerm5887); if (state.failed) return retval; + if ( state.backtracking==0 ) { + DATETIME168_tree = (Object)adaptor.create(DATETIME168); + adaptor.addChild(root_0, DATETIME168_tree); + } + + } + break; + case 10 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:740:11: STAR + { + root_0 = (Object)adaptor.nil(); + + + STAR169=(Token)match(input,STAR,FOLLOW_STAR_in_ftsFieldGroupProximityTerm5899); if (state.failed) return retval; + if ( state.backtracking==0 ) { + STAR169_tree = (Object)adaptor.create(STAR169); + adaptor.addChild(root_0, STAR169_tree); + } + + } + break; + case 11 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:741:11: URI identifier + { + root_0 = (Object)adaptor.nil(); + + + URI170=(Token)match(input,URI,FOLLOW_URI_in_ftsFieldGroupProximityTerm5911); if (state.failed) return retval; + if ( state.backtracking==0 ) { + URI170_tree = (Object)adaptor.create(URI170); + adaptor.addChild(root_0, URI170_tree); + } + + pushFollow(FOLLOW_identifier_in_ftsFieldGroupProximityTerm5913); + identifier171=identifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, identifier171.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupProximityTerm" + + + public static class proximityGroup_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "proximityGroup" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:744:1: proximityGroup : STAR ( LPAREN ( DECIMAL_INTEGER_LITERAL )? RPAREN )? -> ^( PROXIMITY ( DECIMAL_INTEGER_LITERAL )? ) ; + public final FTSParser.proximityGroup_return proximityGroup() throws RecognitionException { + FTSParser.proximityGroup_return retval = new FTSParser.proximityGroup_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token STAR172=null; + Token LPAREN173=null; + Token DECIMAL_INTEGER_LITERAL174=null; + Token RPAREN175=null; + + Object STAR172_tree=null; + Object LPAREN173_tree=null; + Object DECIMAL_INTEGER_LITERAL174_tree=null; + Object RPAREN175_tree=null; + RewriteRuleTokenStream stream_DECIMAL_INTEGER_LITERAL=new RewriteRuleTokenStream(adaptor,"token DECIMAL_INTEGER_LITERAL"); + RewriteRuleTokenStream stream_STAR=new RewriteRuleTokenStream(adaptor,"token STAR"); + RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN"); + RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:745:9: ( STAR ( LPAREN ( DECIMAL_INTEGER_LITERAL )? RPAREN )? -> ^( PROXIMITY ( DECIMAL_INTEGER_LITERAL )? ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:746:9: STAR ( LPAREN ( DECIMAL_INTEGER_LITERAL )? RPAREN )? + { + STAR172=(Token)match(input,STAR,FOLLOW_STAR_in_proximityGroup5946); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_STAR.add(STAR172); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:746:14: ( LPAREN ( DECIMAL_INTEGER_LITERAL )? RPAREN )? + int alt64=2; + int LA64_0 = input.LA(1); + if ( (LA64_0==LPAREN) ) { + alt64=1; + } + switch (alt64) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:746:15: LPAREN ( DECIMAL_INTEGER_LITERAL )? RPAREN + { + LPAREN173=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_proximityGroup5949); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LPAREN.add(LPAREN173); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:746:22: ( DECIMAL_INTEGER_LITERAL )? + int alt63=2; + int LA63_0 = input.LA(1); + if ( (LA63_0==DECIMAL_INTEGER_LITERAL) ) { + alt63=1; + } + switch (alt63) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:746:22: DECIMAL_INTEGER_LITERAL + { + DECIMAL_INTEGER_LITERAL174=(Token)match(input,DECIMAL_INTEGER_LITERAL,FOLLOW_DECIMAL_INTEGER_LITERAL_in_proximityGroup5951); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DECIMAL_INTEGER_LITERAL.add(DECIMAL_INTEGER_LITERAL174); + + } + break; + + } + + RPAREN175=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_proximityGroup5954); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RPAREN.add(RPAREN175); + + } + break; + + } + + // AST REWRITE + // elements: DECIMAL_INTEGER_LITERAL + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 747:17: -> ^( PROXIMITY ( DECIMAL_INTEGER_LITERAL )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:748:25: ^( PROXIMITY ( DECIMAL_INTEGER_LITERAL )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PROXIMITY, "PROXIMITY"), root_1); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:748:37: ( DECIMAL_INTEGER_LITERAL )? + if ( stream_DECIMAL_INTEGER_LITERAL.hasNext() ) { + adaptor.addChild(root_1, stream_DECIMAL_INTEGER_LITERAL.nextNode()); + } + stream_DECIMAL_INTEGER_LITERAL.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "proximityGroup" + + + public static class ftsFieldGroupRange_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsFieldGroupRange" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:751:1: ftsFieldGroupRange : ( ftsRangeWord DOTDOT ftsRangeWord -> INCLUSIVE ftsRangeWord ftsRangeWord INCLUSIVE | range_left ftsRangeWord TO ftsRangeWord range_right -> range_left ftsRangeWord ftsRangeWord range_right ); + public final FTSParser.ftsFieldGroupRange_return ftsFieldGroupRange() throws RecognitionException { + FTSParser.ftsFieldGroupRange_return retval = new FTSParser.ftsFieldGroupRange_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token DOTDOT177=null; + Token TO181=null; + ParserRuleReturnScope ftsRangeWord176 =null; + ParserRuleReturnScope ftsRangeWord178 =null; + ParserRuleReturnScope range_left179 =null; + ParserRuleReturnScope ftsRangeWord180 =null; + ParserRuleReturnScope ftsRangeWord182 =null; + ParserRuleReturnScope range_right183 =null; + + Object DOTDOT177_tree=null; + Object TO181_tree=null; + RewriteRuleTokenStream stream_DOTDOT=new RewriteRuleTokenStream(adaptor,"token DOTDOT"); + RewriteRuleTokenStream stream_TO=new RewriteRuleTokenStream(adaptor,"token TO"); + RewriteRuleSubtreeStream stream_range_left=new RewriteRuleSubtreeStream(adaptor,"rule range_left"); + RewriteRuleSubtreeStream stream_ftsRangeWord=new RewriteRuleSubtreeStream(adaptor,"rule ftsRangeWord"); + RewriteRuleSubtreeStream stream_range_right=new RewriteRuleSubtreeStream(adaptor,"rule range_right"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:752:9: ( ftsRangeWord DOTDOT ftsRangeWord -> INCLUSIVE ftsRangeWord ftsRangeWord INCLUSIVE | range_left ftsRangeWord TO ftsRangeWord range_right -> range_left ftsRangeWord ftsRangeWord range_right ) + int alt65=2; + int LA65_0 = input.LA(1); + if ( (LA65_0==DATETIME||LA65_0==DECIMAL_INTEGER_LITERAL||LA65_0==FLOATING_POINT_LITERAL||(LA65_0 >= FTSPHRASE && LA65_0 <= FTSWORD)||LA65_0==ID||LA65_0==STAR||LA65_0==URI) ) { + alt65=1; + } + else if ( ((LA65_0 >= LSQUARE && LA65_0 <= LT)) ) { + alt65=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 65, 0, input); + throw nvae; + } + + switch (alt65) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:753:9: ftsRangeWord DOTDOT ftsRangeWord + { + pushFollow(FOLLOW_ftsRangeWord_in_ftsFieldGroupRange6038); + ftsRangeWord176=ftsRangeWord(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsRangeWord.add(ftsRangeWord176.getTree()); + DOTDOT177=(Token)match(input,DOTDOT,FOLLOW_DOTDOT_in_ftsFieldGroupRange6040); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DOTDOT.add(DOTDOT177); + + pushFollow(FOLLOW_ftsRangeWord_in_ftsFieldGroupRange6042); + ftsRangeWord178=ftsRangeWord(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsRangeWord.add(ftsRangeWord178.getTree()); + // AST REWRITE + // elements: ftsRangeWord, ftsRangeWord + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 754:17: -> INCLUSIVE ftsRangeWord ftsRangeWord INCLUSIVE + { + adaptor.addChild(root_0, (Object)adaptor.create(INCLUSIVE, "INCLUSIVE")); + adaptor.addChild(root_0, stream_ftsRangeWord.nextTree()); + adaptor.addChild(root_0, stream_ftsRangeWord.nextTree()); + adaptor.addChild(root_0, (Object)adaptor.create(INCLUSIVE, "INCLUSIVE")); + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:755:11: range_left ftsRangeWord TO ftsRangeWord range_right + { + pushFollow(FOLLOW_range_left_in_ftsFieldGroupRange6080); + range_left179=range_left(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_range_left.add(range_left179.getTree()); + pushFollow(FOLLOW_ftsRangeWord_in_ftsFieldGroupRange6082); + ftsRangeWord180=ftsRangeWord(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsRangeWord.add(ftsRangeWord180.getTree()); + TO181=(Token)match(input,TO,FOLLOW_TO_in_ftsFieldGroupRange6084); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_TO.add(TO181); + + pushFollow(FOLLOW_ftsRangeWord_in_ftsFieldGroupRange6086); + ftsRangeWord182=ftsRangeWord(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ftsRangeWord.add(ftsRangeWord182.getTree()); + pushFollow(FOLLOW_range_right_in_ftsFieldGroupRange6088); + range_right183=range_right(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_range_right.add(range_right183.getTree()); + // AST REWRITE + // elements: ftsRangeWord, range_left, range_right, ftsRangeWord + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 756:17: -> range_left ftsRangeWord ftsRangeWord range_right + { + adaptor.addChild(root_0, stream_range_left.nextTree()); + adaptor.addChild(root_0, stream_ftsRangeWord.nextTree()); + adaptor.addChild(root_0, stream_ftsRangeWord.nextTree()); + adaptor.addChild(root_0, stream_range_right.nextTree()); + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsFieldGroupRange" + + + public static class range_left_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "range_left" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:759:1: range_left : ( LSQUARE -> INCLUSIVE | LT -> EXCLUSIVE ); + public final FTSParser.range_left_return range_left() throws RecognitionException { + FTSParser.range_left_return retval = new FTSParser.range_left_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token LSQUARE184=null; + Token LT185=null; + + Object LSQUARE184_tree=null; + Object LT185_tree=null; + RewriteRuleTokenStream stream_LSQUARE=new RewriteRuleTokenStream(adaptor,"token LSQUARE"); + RewriteRuleTokenStream stream_LT=new RewriteRuleTokenStream(adaptor,"token LT"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:760:9: ( LSQUARE -> INCLUSIVE | LT -> EXCLUSIVE ) + int alt66=2; + int LA66_0 = input.LA(1); + if ( (LA66_0==LSQUARE) ) { + alt66=1; + } + else if ( (LA66_0==LT) ) { + alt66=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 66, 0, input); + throw nvae; + } + + switch (alt66) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:761:9: LSQUARE + { + LSQUARE184=(Token)match(input,LSQUARE,FOLLOW_LSQUARE_in_range_left6147); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LSQUARE.add(LSQUARE184); + + // AST REWRITE + // elements: + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 762:17: -> INCLUSIVE + { + adaptor.addChild(root_0, (Object)adaptor.create(INCLUSIVE, "INCLUSIVE")); + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:763:11: LT + { + LT185=(Token)match(input,LT,FOLLOW_LT_in_range_left6179); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_LT.add(LT185); + + // AST REWRITE + // elements: + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 764:17: -> EXCLUSIVE + { + adaptor.addChild(root_0, (Object)adaptor.create(EXCLUSIVE, "EXCLUSIVE")); + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "range_left" + + + public static class range_right_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "range_right" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:767:1: range_right : ( RSQUARE -> INCLUSIVE | GT -> EXCLUSIVE ); + public final FTSParser.range_right_return range_right() throws RecognitionException { + FTSParser.range_right_return retval = new FTSParser.range_right_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token RSQUARE186=null; + Token GT187=null; + + Object RSQUARE186_tree=null; + Object GT187_tree=null; + RewriteRuleTokenStream stream_RSQUARE=new RewriteRuleTokenStream(adaptor,"token RSQUARE"); + RewriteRuleTokenStream stream_GT=new RewriteRuleTokenStream(adaptor,"token GT"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:768:9: ( RSQUARE -> INCLUSIVE | GT -> EXCLUSIVE ) + int alt67=2; + int LA67_0 = input.LA(1); + if ( (LA67_0==RSQUARE) ) { + alt67=1; + } + else if ( (LA67_0==GT) ) { + alt67=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 67, 0, input); + throw nvae; + } + + switch (alt67) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:769:9: RSQUARE + { + RSQUARE186=(Token)match(input,RSQUARE,FOLLOW_RSQUARE_in_range_right6232); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_RSQUARE.add(RSQUARE186); + + // AST REWRITE + // elements: + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 770:17: -> INCLUSIVE + { + adaptor.addChild(root_0, (Object)adaptor.create(INCLUSIVE, "INCLUSIVE")); + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:771:11: GT + { + GT187=(Token)match(input,GT,FOLLOW_GT_in_range_right6264); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_GT.add(GT187); + + // AST REWRITE + // elements: + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 772:17: -> EXCLUSIVE + { + adaptor.addChild(root_0, (Object)adaptor.create(EXCLUSIVE, "EXCLUSIVE")); + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "range_right" + + + public static class fieldReference_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "fieldReference" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:777:1: fieldReference : ( AT )? ( ( prefix )=> prefix | uri )? identifier -> ^( FIELD_REF identifier ( prefix )? ( uri )? ) ; + public final FTSParser.fieldReference_return fieldReference() throws RecognitionException { + FTSParser.fieldReference_return retval = new FTSParser.fieldReference_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token AT188=null; + ParserRuleReturnScope prefix189 =null; + ParserRuleReturnScope uri190 =null; + ParserRuleReturnScope identifier191 =null; + + Object AT188_tree=null; + RewriteRuleTokenStream stream_AT=new RewriteRuleTokenStream(adaptor,"token AT"); + RewriteRuleSubtreeStream stream_identifier=new RewriteRuleSubtreeStream(adaptor,"rule identifier"); + RewriteRuleSubtreeStream stream_prefix=new RewriteRuleSubtreeStream(adaptor,"rule prefix"); + RewriteRuleSubtreeStream stream_uri=new RewriteRuleSubtreeStream(adaptor,"rule uri"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:778:9: ( ( AT )? ( ( prefix )=> prefix | uri )? identifier -> ^( FIELD_REF identifier ( prefix )? ( uri )? ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:779:9: ( AT )? ( ( prefix )=> prefix | uri )? identifier + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:779:9: ( AT )? + int alt68=2; + int LA68_0 = input.LA(1); + if ( (LA68_0==AT) ) { + alt68=1; + } + switch (alt68) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:779:9: AT + { + AT188=(Token)match(input,AT,FOLLOW_AT_in_fieldReference6320); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_AT.add(AT188); + + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:780:9: ( ( prefix )=> prefix | uri )? + int alt69=3; + switch ( input.LA(1) ) { + case ID: + { + int LA69_1 = input.LA(2); + if ( (LA69_1==DOT) ) { + int LA69_7 = input.LA(3); + if ( (LA69_7==ID) ) { + int LA69_9 = input.LA(4); + if ( (LA69_9==COLON) ) { + int LA69_8 = input.LA(5); + if ( (LA69_8==ID) ) { + int LA69_11 = input.LA(6); + if ( (LA69_11==DOT) ) { + int LA69_16 = input.LA(7); + if ( (LA69_16==ID) ) { + int LA69_18 = input.LA(8); + if ( (synpred39_FTS()) ) { + alt69=1; + } + } + } + else if ( (LA69_11==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + else if ( (LA69_8==TO) ) { + int LA69_12 = input.LA(6); + if ( (LA69_12==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + else if ( (LA69_8==OR) && (synpred39_FTS())) { + alt69=1; + } + else if ( (LA69_8==AND) && (synpred39_FTS())) { + alt69=1; + } + else if ( (LA69_8==NOT) ) { + int LA69_15 = input.LA(6); + if ( (LA69_15==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + } + } + } + else if ( (LA69_1==COLON) ) { + int LA69_8 = input.LA(3); + if ( (LA69_8==ID) ) { + int LA69_11 = input.LA(4); + if ( (LA69_11==DOT) ) { + int LA69_16 = input.LA(5); + if ( (LA69_16==ID) ) { + int LA69_18 = input.LA(6); + if ( (synpred39_FTS()) ) { + alt69=1; + } + } + } + else if ( (LA69_11==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + else if ( (LA69_8==TO) ) { + int LA69_12 = input.LA(4); + if ( (LA69_12==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + else if ( (LA69_8==OR) && (synpred39_FTS())) { + alt69=1; + } + else if ( (LA69_8==AND) && (synpred39_FTS())) { + alt69=1; + } + else if ( (LA69_8==NOT) ) { + int LA69_15 = input.LA(4); + if ( (LA69_15==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + } + } + break; + case TO: + { + int LA69_2 = input.LA(2); + if ( (LA69_2==COLON) ) { + int LA69_8 = input.LA(3); + if ( (LA69_8==ID) ) { + int LA69_11 = input.LA(4); + if ( (LA69_11==DOT) ) { + int LA69_16 = input.LA(5); + if ( (LA69_16==ID) ) { + int LA69_18 = input.LA(6); + if ( (synpred39_FTS()) ) { + alt69=1; + } + } + } + else if ( (LA69_11==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + else if ( (LA69_8==TO) ) { + int LA69_12 = input.LA(4); + if ( (LA69_12==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + else if ( (LA69_8==OR) && (synpred39_FTS())) { + alt69=1; + } + else if ( (LA69_8==AND) && (synpred39_FTS())) { + alt69=1; + } + else if ( (LA69_8==NOT) ) { + int LA69_15 = input.LA(4); + if ( (LA69_15==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + } + } + break; + case OR: + { + int LA69_3 = input.LA(2); + if ( (LA69_3==COLON) ) { + int LA69_8 = input.LA(3); + if ( (LA69_8==ID) ) { + int LA69_11 = input.LA(4); + if ( (LA69_11==DOT) ) { + int LA69_16 = input.LA(5); + if ( (LA69_16==ID) ) { + int LA69_18 = input.LA(6); + if ( (synpred39_FTS()) ) { + alt69=1; + } + } + } + else if ( (LA69_11==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + else if ( (LA69_8==TO) ) { + int LA69_12 = input.LA(4); + if ( (LA69_12==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + else if ( (LA69_8==OR) && (synpred39_FTS())) { + alt69=1; + } + else if ( (LA69_8==AND) && (synpred39_FTS())) { + alt69=1; + } + else if ( (LA69_8==NOT) ) { + int LA69_15 = input.LA(4); + if ( (LA69_15==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + } + } + break; + case AND: + { + int LA69_4 = input.LA(2); + if ( (LA69_4==COLON) ) { + int LA69_8 = input.LA(3); + if ( (LA69_8==ID) ) { + int LA69_11 = input.LA(4); + if ( (LA69_11==DOT) ) { + int LA69_16 = input.LA(5); + if ( (LA69_16==ID) ) { + int LA69_18 = input.LA(6); + if ( (synpred39_FTS()) ) { + alt69=1; + } + } + } + else if ( (LA69_11==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + else if ( (LA69_8==TO) ) { + int LA69_12 = input.LA(4); + if ( (LA69_12==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + else if ( (LA69_8==OR) && (synpred39_FTS())) { + alt69=1; + } + else if ( (LA69_8==AND) && (synpred39_FTS())) { + alt69=1; + } + else if ( (LA69_8==NOT) ) { + int LA69_15 = input.LA(4); + if ( (LA69_15==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + } + } + break; + case NOT: + { + int LA69_5 = input.LA(2); + if ( (LA69_5==COLON) ) { + int LA69_8 = input.LA(3); + if ( (LA69_8==ID) ) { + int LA69_11 = input.LA(4); + if ( (LA69_11==DOT) ) { + int LA69_16 = input.LA(5); + if ( (LA69_16==ID) ) { + int LA69_18 = input.LA(6); + if ( (synpred39_FTS()) ) { + alt69=1; + } + } + } + else if ( (LA69_11==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + else if ( (LA69_8==TO) ) { + int LA69_12 = input.LA(4); + if ( (LA69_12==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + else if ( (LA69_8==OR) && (synpred39_FTS())) { + alt69=1; + } + else if ( (LA69_8==AND) && (synpred39_FTS())) { + alt69=1; + } + else if ( (LA69_8==NOT) ) { + int LA69_15 = input.LA(4); + if ( (LA69_15==COLON) && (synpred39_FTS())) { + alt69=1; + } + } + } + } + break; + case URI: + { + alt69=2; + } + break; + } + switch (alt69) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:781:19: ( prefix )=> prefix + { + pushFollow(FOLLOW_prefix_in_fieldReference6357); + prefix189=prefix(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_prefix.add(prefix189.getTree()); + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:782:19: uri + { + pushFollow(FOLLOW_uri_in_fieldReference6377); + uri190=uri(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_uri.add(uri190.getTree()); + } + break; + + } + + pushFollow(FOLLOW_identifier_in_fieldReference6398); + identifier191=identifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identifier.add(identifier191.getTree()); + // AST REWRITE + // elements: identifier, prefix, uri + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 785:17: -> ^( FIELD_REF identifier ( prefix )? ( uri )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:786:25: ^( FIELD_REF identifier ( prefix )? ( uri )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FIELD_REF, "FIELD_REF"), root_1); + adaptor.addChild(root_1, stream_identifier.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:786:48: ( prefix )? + if ( stream_prefix.hasNext() ) { + adaptor.addChild(root_1, stream_prefix.nextTree()); + } + stream_prefix.reset(); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:786:56: ( uri )? + if ( stream_uri.hasNext() ) { + adaptor.addChild(root_1, stream_uri.nextTree()); + } + stream_uri.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "fieldReference" + + + public static class tempReference_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "tempReference" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:789:1: tempReference : ( AT )? ( prefix | uri )? identifier -> ^( FIELD_REF identifier ( prefix )? ( uri )? ) ; + public final FTSParser.tempReference_return tempReference() throws RecognitionException { + FTSParser.tempReference_return retval = new FTSParser.tempReference_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token AT192=null; + ParserRuleReturnScope prefix193 =null; + ParserRuleReturnScope uri194 =null; + ParserRuleReturnScope identifier195 =null; + + Object AT192_tree=null; + RewriteRuleTokenStream stream_AT=new RewriteRuleTokenStream(adaptor,"token AT"); + RewriteRuleSubtreeStream stream_identifier=new RewriteRuleSubtreeStream(adaptor,"rule identifier"); + RewriteRuleSubtreeStream stream_prefix=new RewriteRuleSubtreeStream(adaptor,"rule prefix"); + RewriteRuleSubtreeStream stream_uri=new RewriteRuleSubtreeStream(adaptor,"rule uri"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:790:9: ( ( AT )? ( prefix | uri )? identifier -> ^( FIELD_REF identifier ( prefix )? ( uri )? ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:791:9: ( AT )? ( prefix | uri )? identifier + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:791:9: ( AT )? + int alt70=2; + int LA70_0 = input.LA(1); + if ( (LA70_0==AT) ) { + alt70=1; + } + switch (alt70) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:791:9: AT + { + AT192=(Token)match(input,AT,FOLLOW_AT_in_tempReference6485); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_AT.add(AT192); + + } + break; + + } + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:792:9: ( prefix | uri )? + int alt71=3; + switch ( input.LA(1) ) { + case ID: + { + int LA71_1 = input.LA(2); + if ( (LA71_1==DOT) ) { + int LA71_7 = input.LA(3); + if ( (LA71_7==ID) ) { + int LA71_10 = input.LA(4); + if ( (LA71_10==COLON) ) { + alt71=1; + } + } + } + else if ( (LA71_1==COLON) ) { + alt71=1; + } + } + break; + case TO: + { + int LA71_2 = input.LA(2); + if ( (LA71_2==COLON) ) { + alt71=1; + } + } + break; + case OR: + { + int LA71_3 = input.LA(2); + if ( (LA71_3==COLON) ) { + alt71=1; + } + } + break; + case AND: + { + int LA71_4 = input.LA(2); + if ( (LA71_4==COLON) ) { + alt71=1; + } + } + break; + case NOT: + { + int LA71_5 = input.LA(2); + if ( (LA71_5==COLON) ) { + alt71=1; + } + } + break; + case URI: + { + alt71=2; + } + break; + } + switch (alt71) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:793:17: prefix + { + pushFollow(FOLLOW_prefix_in_tempReference6514); + prefix193=prefix(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_prefix.add(prefix193.getTree()); + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:794:19: uri + { + pushFollow(FOLLOW_uri_in_tempReference6534); + uri194=uri(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_uri.add(uri194.getTree()); + } + break; + + } + + pushFollow(FOLLOW_identifier_in_tempReference6555); + identifier195=identifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identifier.add(identifier195.getTree()); + // AST REWRITE + // elements: identifier, uri, prefix + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 797:17: -> ^( FIELD_REF identifier ( prefix )? ( uri )? ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:798:25: ^( FIELD_REF identifier ( prefix )? ( uri )? ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(FIELD_REF, "FIELD_REF"), root_1); + adaptor.addChild(root_1, stream_identifier.nextTree()); + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:798:48: ( prefix )? + if ( stream_prefix.hasNext() ) { + adaptor.addChild(root_1, stream_prefix.nextTree()); + } + stream_prefix.reset(); + + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:798:56: ( uri )? + if ( stream_uri.hasNext() ) { + adaptor.addChild(root_1, stream_uri.nextTree()); + } + stream_uri.reset(); + + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "tempReference" + + + public static class prefix_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "prefix" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:801:1: prefix : identifier COLON -> ^( PREFIX identifier ) ; + public final FTSParser.prefix_return prefix() throws RecognitionException { + FTSParser.prefix_return retval = new FTSParser.prefix_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token COLON197=null; + ParserRuleReturnScope identifier196 =null; + + Object COLON197_tree=null; + RewriteRuleTokenStream stream_COLON=new RewriteRuleTokenStream(adaptor,"token COLON"); + RewriteRuleSubtreeStream stream_identifier=new RewriteRuleSubtreeStream(adaptor,"rule identifier"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:802:9: ( identifier COLON -> ^( PREFIX identifier ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:803:9: identifier COLON + { + pushFollow(FOLLOW_identifier_in_prefix6642); + identifier196=identifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) stream_identifier.add(identifier196.getTree()); + COLON197=(Token)match(input,COLON,FOLLOW_COLON_in_prefix6644); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_COLON.add(COLON197); + + // AST REWRITE + // elements: identifier + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 804:17: -> ^( PREFIX identifier ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:805:25: ^( PREFIX identifier ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(PREFIX, "PREFIX"), root_1); + adaptor.addChild(root_1, stream_identifier.nextTree()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "prefix" + + + public static class uri_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "uri" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:808:1: uri : URI -> ^( NAME_SPACE URI ) ; + public final FTSParser.uri_return uri() throws RecognitionException { + FTSParser.uri_return retval = new FTSParser.uri_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token URI198=null; + + Object URI198_tree=null; + RewriteRuleTokenStream stream_URI=new RewriteRuleTokenStream(adaptor,"token URI"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:809:9: ( URI -> ^( NAME_SPACE URI ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:810:9: URI + { + URI198=(Token)match(input,URI,FOLLOW_URI_in_uri6725); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_URI.add(URI198); + + // AST REWRITE + // elements: URI + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 811:17: -> ^( NAME_SPACE URI ) + { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:812:25: ^( NAME_SPACE URI ) + { + Object root_1 = (Object)adaptor.nil(); + root_1 = (Object)adaptor.becomeRoot((Object)adaptor.create(NAME_SPACE, "NAME_SPACE"), root_1); + adaptor.addChild(root_1, stream_URI.nextNode()); + adaptor.addChild(root_0, root_1); + } + + } + + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "uri" + + + public static class identifier_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "identifier" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:815:1: identifier : ( ( ID DOT ID )=>id1= ID DOT id2= ID ->| ID -> ID | TO -> TO | OR -> OR | AND -> AND | NOT -> NOT ); + public final FTSParser.identifier_return identifier() throws RecognitionException { + FTSParser.identifier_return retval = new FTSParser.identifier_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token id1=null; + Token id2=null; + Token DOT199=null; + Token ID200=null; + Token TO201=null; + Token OR202=null; + Token AND203=null; + Token NOT204=null; + + Object id1_tree=null; + Object id2_tree=null; + Object DOT199_tree=null; + Object ID200_tree=null; + Object TO201_tree=null; + Object OR202_tree=null; + Object AND203_tree=null; + Object NOT204_tree=null; + RewriteRuleTokenStream stream_NOT=new RewriteRuleTokenStream(adaptor,"token NOT"); + RewriteRuleTokenStream stream_OR=new RewriteRuleTokenStream(adaptor,"token OR"); + RewriteRuleTokenStream stream_AND=new RewriteRuleTokenStream(adaptor,"token AND"); + RewriteRuleTokenStream stream_DOT=new RewriteRuleTokenStream(adaptor,"token DOT"); + RewriteRuleTokenStream stream_ID=new RewriteRuleTokenStream(adaptor,"token ID"); + RewriteRuleTokenStream stream_TO=new RewriteRuleTokenStream(adaptor,"token TO"); + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:816:9: ( ( ID DOT ID )=>id1= ID DOT id2= ID ->| ID -> ID | TO -> TO | OR -> OR | AND -> AND | NOT -> NOT ) + int alt72=6; + switch ( input.LA(1) ) { + case ID: + { + int LA72_1 = input.LA(2); + if ( (LA72_1==DOT) ) { + int LA72_6 = input.LA(3); + if ( (LA72_6==ID) ) { + int LA72_8 = input.LA(4); + if ( (synpred40_FTS()) ) { + alt72=1; + } + else if ( (true) ) { + alt72=2; + } + + } + else if ( (LA72_6==EOF||(LA72_6 >= AMP && LA72_6 <= BAR)||LA72_6==CARAT||LA72_6==COMMA||LA72_6==DATETIME||LA72_6==DECIMAL_INTEGER_LITERAL||LA72_6==DOT||LA72_6==EQUALS||LA72_6==EXCLAMATION||LA72_6==FLOATING_POINT_LITERAL||(LA72_6 >= FTSPHRASE && LA72_6 <= FTSWORD)||(LA72_6 >= LPAREN && LA72_6 <= LT)||LA72_6==MINUS||LA72_6==NOT||(LA72_6 >= OR && LA72_6 <= PERCENT)||LA72_6==PLUS||LA72_6==QUESTION_MARK||LA72_6==RPAREN||LA72_6==STAR||(LA72_6 >= TILDA && LA72_6 <= TO)||LA72_6==URI) ) { + alt72=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + for (int nvaeConsume = 0; nvaeConsume < 3 - 1; nvaeConsume++) { + input.consume(); + } + NoViableAltException nvae = + new NoViableAltException("", 72, 6, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + else if ( (LA72_1==EOF||(LA72_1 >= AMP && LA72_1 <= BAR)||(LA72_1 >= CARAT && LA72_1 <= COMMA)||LA72_1==DATETIME||LA72_1==DECIMAL_INTEGER_LITERAL||LA72_1==DOTDOT||LA72_1==EQUALS||LA72_1==EXCLAMATION||LA72_1==FLOATING_POINT_LITERAL||(LA72_1 >= FTSPHRASE && LA72_1 <= FTSWORD)||LA72_1==GT||LA72_1==ID||(LA72_1 >= LPAREN && LA72_1 <= LT)||LA72_1==MINUS||LA72_1==NOT||(LA72_1 >= OR && LA72_1 <= PERCENT)||LA72_1==PLUS||LA72_1==QUESTION_MARK||(LA72_1 >= RPAREN && LA72_1 <= RSQUARE)||LA72_1==STAR||(LA72_1 >= TILDA && LA72_1 <= TO)||LA72_1==URI) ) { + alt72=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + int nvaeMark = input.mark(); + try { + input.consume(); + NoViableAltException nvae = + new NoViableAltException("", 72, 1, input); + throw nvae; + } finally { + input.rewind(nvaeMark); + } + } + + } + break; + case TO: + { + alt72=3; + } + break; + case OR: + { + alt72=4; + } + break; + case AND: + { + alt72=5; + } + break; + case NOT: + { + alt72=6; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 72, 0, input); + throw nvae; + } + switch (alt72) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:817:9: ( ID DOT ID )=>id1= ID DOT id2= ID + { + id1=(Token)match(input,ID,FOLLOW_ID_in_identifier6827); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ID.add(id1); + + DOT199=(Token)match(input,DOT,FOLLOW_DOT_in_identifier6829); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_DOT.add(DOT199); + + id2=(Token)match(input,ID,FOLLOW_ID_in_identifier6833); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ID.add(id2); + + // AST REWRITE + // elements: + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 819:17: -> + { + adaptor.addChild(root_0, new CommonTree(new CommonToken(FTSLexer.ID, (id1!=null?id1.getText():null)+(DOT199!=null?DOT199.getText():null)+(id2!=null?id2.getText():null)))); + } + + + retval.tree = root_0; + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:821:12: ID + { + ID200=(Token)match(input,ID,FOLLOW_ID_in_identifier6882); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_ID.add(ID200); + + // AST REWRITE + // elements: ID + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 822:17: -> ID + { + adaptor.addChild(root_0, stream_ID.nextNode()); + } + + + retval.tree = root_0; + } + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:825:12: TO + { + TO201=(Token)match(input,TO,FOLLOW_TO_in_identifier6949); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_TO.add(TO201); + + // AST REWRITE + // elements: TO + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 826:17: -> TO + { + adaptor.addChild(root_0, stream_TO.nextNode()); + } + + + retval.tree = root_0; + } + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:827:12: OR + { + OR202=(Token)match(input,OR,FOLLOW_OR_in_identifier6987); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_OR.add(OR202); + + // AST REWRITE + // elements: OR + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 828:17: -> OR + { + adaptor.addChild(root_0, stream_OR.nextNode()); + } + + + retval.tree = root_0; + } + + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:829:12: AND + { + AND203=(Token)match(input,AND,FOLLOW_AND_in_identifier7025); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_AND.add(AND203); + + // AST REWRITE + // elements: AND + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 830:17: -> AND + { + adaptor.addChild(root_0, stream_AND.nextNode()); + } + + + retval.tree = root_0; + } + + } + break; + case 6 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:831:12: NOT + { + NOT204=(Token)match(input,NOT,FOLLOW_NOT_in_identifier7064); if (state.failed) return retval; + if ( state.backtracking==0 ) stream_NOT.add(NOT204); + + // AST REWRITE + // elements: NOT + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + if ( state.backtracking==0 ) { + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.getTree():null); + + root_0 = (Object)adaptor.nil(); + // 832:17: -> NOT + { + adaptor.addChild(root_0, stream_NOT.nextNode()); + } + + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "identifier" + + + public static class ftsWord_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsWord" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:835:1: ftsWord : ( ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase DOT | COMMA ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) | ( DOT | COMMA ) ftsWordBase | ftsWordBase ); + public final FTSParser.ftsWord_return ftsWord() throws RecognitionException { + FTSParser.ftsWord_return retval = new FTSParser.ftsWord_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set205=null; + Token set207=null; + Token set209=null; + Token set211=null; + Token set213=null; + Token set216=null; + Token set218=null; + Token set220=null; + Token set222=null; + Token set224=null; + Token set226=null; + Token set228=null; + Token set230=null; + Token set232=null; + Token set234=null; + Token set236=null; + Token set238=null; + Token set240=null; + Token set241=null; + Token set243=null; + Token set245=null; + Token set247=null; + Token set250=null; + Token set252=null; + Token set254=null; + Token set256=null; + Token set258=null; + Token set260=null; + Token set262=null; + Token set264=null; + Token set266=null; + Token set268=null; + Token set269=null; + Token set271=null; + Token set273=null; + Token set276=null; + Token set278=null; + Token set280=null; + Token set282=null; + Token set284=null; + Token set286=null; + Token set288=null; + Token set289=null; + Token set291=null; + Token set294=null; + Token set296=null; + Token set298=null; + Token set300=null; + Token set301=null; + ParserRuleReturnScope ftsWordBase206 =null; + ParserRuleReturnScope ftsWordBase208 =null; + ParserRuleReturnScope ftsWordBase210 =null; + ParserRuleReturnScope ftsWordBase212 =null; + ParserRuleReturnScope ftsWordBase214 =null; + ParserRuleReturnScope ftsWordBase215 =null; + ParserRuleReturnScope ftsWordBase217 =null; + ParserRuleReturnScope ftsWordBase219 =null; + ParserRuleReturnScope ftsWordBase221 =null; + ParserRuleReturnScope ftsWordBase223 =null; + ParserRuleReturnScope ftsWordBase225 =null; + ParserRuleReturnScope ftsWordBase227 =null; + ParserRuleReturnScope ftsWordBase229 =null; + ParserRuleReturnScope ftsWordBase231 =null; + ParserRuleReturnScope ftsWordBase233 =null; + ParserRuleReturnScope ftsWordBase235 =null; + ParserRuleReturnScope ftsWordBase237 =null; + ParserRuleReturnScope ftsWordBase239 =null; + ParserRuleReturnScope ftsWordBase242 =null; + ParserRuleReturnScope ftsWordBase244 =null; + ParserRuleReturnScope ftsWordBase246 =null; + ParserRuleReturnScope ftsWordBase248 =null; + ParserRuleReturnScope ftsWordBase249 =null; + ParserRuleReturnScope ftsWordBase251 =null; + ParserRuleReturnScope ftsWordBase253 =null; + ParserRuleReturnScope ftsWordBase255 =null; + ParserRuleReturnScope ftsWordBase257 =null; + ParserRuleReturnScope ftsWordBase259 =null; + ParserRuleReturnScope ftsWordBase261 =null; + ParserRuleReturnScope ftsWordBase263 =null; + ParserRuleReturnScope ftsWordBase265 =null; + ParserRuleReturnScope ftsWordBase267 =null; + ParserRuleReturnScope ftsWordBase270 =null; + ParserRuleReturnScope ftsWordBase272 =null; + ParserRuleReturnScope ftsWordBase274 =null; + ParserRuleReturnScope ftsWordBase275 =null; + ParserRuleReturnScope ftsWordBase277 =null; + ParserRuleReturnScope ftsWordBase279 =null; + ParserRuleReturnScope ftsWordBase281 =null; + ParserRuleReturnScope ftsWordBase283 =null; + ParserRuleReturnScope ftsWordBase285 =null; + ParserRuleReturnScope ftsWordBase287 =null; + ParserRuleReturnScope ftsWordBase290 =null; + ParserRuleReturnScope ftsWordBase292 =null; + ParserRuleReturnScope ftsWordBase293 =null; + ParserRuleReturnScope ftsWordBase295 =null; + ParserRuleReturnScope ftsWordBase297 =null; + ParserRuleReturnScope ftsWordBase299 =null; + ParserRuleReturnScope ftsWordBase302 =null; + ParserRuleReturnScope ftsWordBase303 =null; + + Object set205_tree=null; + Object set207_tree=null; + Object set209_tree=null; + Object set211_tree=null; + Object set213_tree=null; + Object set216_tree=null; + Object set218_tree=null; + Object set220_tree=null; + Object set222_tree=null; + Object set224_tree=null; + Object set226_tree=null; + Object set228_tree=null; + Object set230_tree=null; + Object set232_tree=null; + Object set234_tree=null; + Object set236_tree=null; + Object set238_tree=null; + Object set240_tree=null; + Object set241_tree=null; + Object set243_tree=null; + Object set245_tree=null; + Object set247_tree=null; + Object set250_tree=null; + Object set252_tree=null; + Object set254_tree=null; + Object set256_tree=null; + Object set258_tree=null; + Object set260_tree=null; + Object set262_tree=null; + Object set264_tree=null; + Object set266_tree=null; + Object set268_tree=null; + Object set269_tree=null; + Object set271_tree=null; + Object set273_tree=null; + Object set276_tree=null; + Object set278_tree=null; + Object set280_tree=null; + Object set282_tree=null; + Object set284_tree=null; + Object set286_tree=null; + Object set288_tree=null; + Object set289_tree=null; + Object set291_tree=null; + Object set294_tree=null; + Object set296_tree=null; + Object set298_tree=null; + Object set300_tree=null; + Object set301_tree=null; + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:836:9: ( ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase DOT | COMMA ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) | ( DOT | COMMA ) ftsWordBase | ftsWordBase ) + int alt73=18; + alt73 = dfa73.predict(input); + switch (alt73) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:837:12: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase + { + root_0 = (Object)adaptor.nil(); + + + set205=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set205)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7188); + ftsWordBase206=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase206.getTree()); + + set207=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set207)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7196); + ftsWordBase208=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase208.getTree()); + + set209=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set209)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7204); + ftsWordBase210=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase210.getTree()); + + set211=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set211)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7212); + ftsWordBase212=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase212.getTree()); + + set213=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set213)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7220); + ftsWordBase214=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase214.getTree()); + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:839:11: ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase DOT | COMMA ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7280); + ftsWordBase215=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase215.getTree()); + + set216=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set216)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7288); + ftsWordBase217=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase217.getTree()); + + set218=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set218)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7296); + ftsWordBase219=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase219.getTree()); + + set220=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set220)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7304); + ftsWordBase221=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase221.getTree()); + + set222=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set222)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7312); + ftsWordBase223=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase223.getTree()); + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:841:12: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) + { + root_0 = (Object)adaptor.nil(); + + + set224=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set224)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7385); + ftsWordBase225=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase225.getTree()); + + set226=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set226)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7393); + ftsWordBase227=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase227.getTree()); + + set228=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set228)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7401); + ftsWordBase229=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase229.getTree()); + + set230=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set230)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7409); + ftsWordBase231=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase231.getTree()); + + set232=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set232)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:843:11: ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7475); + ftsWordBase233=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase233.getTree()); + + set234=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set234)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7483); + ftsWordBase235=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase235.getTree()); + + set236=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set236)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7491); + ftsWordBase237=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase237.getTree()); + + set238=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set238)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7499); + ftsWordBase239=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase239.getTree()); + + set240=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set240)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:845:12: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase + { + root_0 = (Object)adaptor.nil(); + + + set241=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set241)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7572); + ftsWordBase242=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase242.getTree()); + + set243=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set243)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7580); + ftsWordBase244=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase244.getTree()); + + set245=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set245)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7588); + ftsWordBase246=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase246.getTree()); + + set247=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set247)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7596); + ftsWordBase248=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase248.getTree()); + + } + break; + case 6 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:847:11: ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7650); + ftsWordBase249=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase249.getTree()); + + set250=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set250)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7658); + ftsWordBase251=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase251.getTree()); + + set252=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set252)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7666); + ftsWordBase253=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase253.getTree()); + + set254=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set254)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7674); + ftsWordBase255=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase255.getTree()); + + } + break; + case 7 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:849:11: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) + { + root_0 = (Object)adaptor.nil(); + + + set256=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set256)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7738); + ftsWordBase257=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase257.getTree()); + + set258=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set258)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7746); + ftsWordBase259=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase259.getTree()); + + set260=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set260)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7754); + ftsWordBase261=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase261.getTree()); + + set262=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set262)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + break; + case 8 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:851:11: ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7812); + ftsWordBase263=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase263.getTree()); + + set264=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set264)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7820); + ftsWordBase265=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase265.getTree()); + + set266=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set266)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7828); + ftsWordBase267=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase267.getTree()); + + set268=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set268)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + break; + case 9 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:853:11: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase + { + root_0 = (Object)adaptor.nil(); + + + set269=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set269)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7892); + ftsWordBase270=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase270.getTree()); + + set271=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set271)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7900); + ftsWordBase272=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase272.getTree()); + + set273=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set273)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7908); + ftsWordBase274=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase274.getTree()); + + } + break; + case 10 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:855:11: ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7954); + ftsWordBase275=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase275.getTree()); + + set276=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set276)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7962); + ftsWordBase277=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase277.getTree()); + + set278=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set278)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord7970); + ftsWordBase279=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase279.getTree()); + + } + break; + case 11 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:857:11: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) + { + root_0 = (Object)adaptor.nil(); + + + set280=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set280)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord8027); + ftsWordBase281=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase281.getTree()); + + set282=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set282)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord8035); + ftsWordBase283=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase283.getTree()); + + set284=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set284)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + break; + case 12 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:859:11: ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_ftsWordBase_in_ftsWord8086); + ftsWordBase285=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase285.getTree()); + + set286=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set286)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord8094); + ftsWordBase287=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase287.getTree()); + + set288=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set288)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + break; + case 13 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:861:11: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase + { + root_0 = (Object)adaptor.nil(); + + + set289=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set289)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord8151); + ftsWordBase290=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase290.getTree()); + + set291=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set291)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord8159); + ftsWordBase292=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase292.getTree()); + + } + break; + case 14 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:863:11: ( ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_ftsWordBase_in_ftsWord8197); + ftsWordBase293=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase293.getTree()); + + set294=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set294)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord8205); + ftsWordBase295=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase295.getTree()); + + } + break; + case 15 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:865:11: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) + { + root_0 = (Object)adaptor.nil(); + + + set296=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set296)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord8253); + ftsWordBase297=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase297.getTree()); + + set298=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set298)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + break; + case 16 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:867:11: ( ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_ftsWordBase_in_ftsWord8295); + ftsWordBase299=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase299.getTree()); + + set300=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set300)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + break; + case 17 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:869:11: ( DOT | COMMA ) ftsWordBase + { + root_0 = (Object)adaptor.nil(); + + + set301=input.LT(1); + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set301)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_ftsWord8319); + ftsWordBase302=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase302.getTree()); + + } + break; + case 18 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:870:11: ftsWordBase + { + root_0 = (Object)adaptor.nil(); + + + pushFollow(FOLLOW_ftsWordBase_in_ftsWord8332); + ftsWordBase303=ftsWordBase(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, ftsWordBase303.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsWord" + + + public static class ftsWordBase_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsWordBase" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:874:1: ftsWordBase : ( ID | FTSWORD | FTSPRE | FTSWILD | NOT | TO | DECIMAL_INTEGER_LITERAL | FLOATING_POINT_LITERAL | STAR | QUESTION_MARK | DATETIME | URI identifier ); + public final FTSParser.ftsWordBase_return ftsWordBase() throws RecognitionException { + FTSParser.ftsWordBase_return retval = new FTSParser.ftsWordBase_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token ID304=null; + Token FTSWORD305=null; + Token FTSPRE306=null; + Token FTSWILD307=null; + Token NOT308=null; + Token TO309=null; + Token DECIMAL_INTEGER_LITERAL310=null; + Token FLOATING_POINT_LITERAL311=null; + Token STAR312=null; + Token QUESTION_MARK313=null; + Token DATETIME314=null; + Token URI315=null; + ParserRuleReturnScope identifier316 =null; + + Object ID304_tree=null; + Object FTSWORD305_tree=null; + Object FTSPRE306_tree=null; + Object FTSWILD307_tree=null; + Object NOT308_tree=null; + Object TO309_tree=null; + Object DECIMAL_INTEGER_LITERAL310_tree=null; + Object FLOATING_POINT_LITERAL311_tree=null; + Object STAR312_tree=null; + Object QUESTION_MARK313_tree=null; + Object DATETIME314_tree=null; + Object URI315_tree=null; + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:875:9: ( ID | FTSWORD | FTSPRE | FTSWILD | NOT | TO | DECIMAL_INTEGER_LITERAL | FLOATING_POINT_LITERAL | STAR | QUESTION_MARK | DATETIME | URI identifier ) + int alt74=12; + switch ( input.LA(1) ) { + case ID: + { + alt74=1; + } + break; + case FTSWORD: + { + alt74=2; + } + break; + case FTSPRE: + { + alt74=3; + } + break; + case FTSWILD: + { + alt74=4; + } + break; + case NOT: + { + alt74=5; + } + break; + case TO: + { + alt74=6; + } + break; + case DECIMAL_INTEGER_LITERAL: + { + alt74=7; + } + break; + case FLOATING_POINT_LITERAL: + { + alt74=8; + } + break; + case STAR: + { + alt74=9; + } + break; + case QUESTION_MARK: + { + alt74=10; + } + break; + case DATETIME: + { + alt74=11; + } + break; + case URI: + { + alt74=12; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 74, 0, input); + throw nvae; + } + switch (alt74) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:876:11: ID + { + root_0 = (Object)adaptor.nil(); + + + ID304=(Token)match(input,ID,FOLLOW_ID_in_ftsWordBase8377); if (state.failed) return retval; + if ( state.backtracking==0 ) { + ID304_tree = (Object)adaptor.create(ID304); + adaptor.addChild(root_0, ID304_tree); + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:877:11: FTSWORD + { + root_0 = (Object)adaptor.nil(); + + + FTSWORD305=(Token)match(input,FTSWORD,FOLLOW_FTSWORD_in_ftsWordBase8389); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FTSWORD305_tree = (Object)adaptor.create(FTSWORD305); + adaptor.addChild(root_0, FTSWORD305_tree); + } + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:878:11: FTSPRE + { + root_0 = (Object)adaptor.nil(); + + + FTSPRE306=(Token)match(input,FTSPRE,FOLLOW_FTSPRE_in_ftsWordBase8401); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FTSPRE306_tree = (Object)adaptor.create(FTSPRE306); + adaptor.addChild(root_0, FTSPRE306_tree); + } + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:879:11: FTSWILD + { + root_0 = (Object)adaptor.nil(); + + + FTSWILD307=(Token)match(input,FTSWILD,FOLLOW_FTSWILD_in_ftsWordBase8414); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FTSWILD307_tree = (Object)adaptor.create(FTSWILD307); + adaptor.addChild(root_0, FTSWILD307_tree); + } + + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:880:11: NOT + { + root_0 = (Object)adaptor.nil(); + + + NOT308=(Token)match(input,NOT,FOLLOW_NOT_in_ftsWordBase8427); if (state.failed) return retval; + if ( state.backtracking==0 ) { + NOT308_tree = (Object)adaptor.create(NOT308); + adaptor.addChild(root_0, NOT308_tree); + } + + } + break; + case 6 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:881:11: TO + { + root_0 = (Object)adaptor.nil(); + + + TO309=(Token)match(input,TO,FOLLOW_TO_in_ftsWordBase8439); if (state.failed) return retval; + if ( state.backtracking==0 ) { + TO309_tree = (Object)adaptor.create(TO309); + adaptor.addChild(root_0, TO309_tree); + } + + } + break; + case 7 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:882:11: DECIMAL_INTEGER_LITERAL + { + root_0 = (Object)adaptor.nil(); + + + DECIMAL_INTEGER_LITERAL310=(Token)match(input,DECIMAL_INTEGER_LITERAL,FOLLOW_DECIMAL_INTEGER_LITERAL_in_ftsWordBase8451); if (state.failed) return retval; + if ( state.backtracking==0 ) { + DECIMAL_INTEGER_LITERAL310_tree = (Object)adaptor.create(DECIMAL_INTEGER_LITERAL310); + adaptor.addChild(root_0, DECIMAL_INTEGER_LITERAL310_tree); + } + + } + break; + case 8 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:883:11: FLOATING_POINT_LITERAL + { + root_0 = (Object)adaptor.nil(); + + + FLOATING_POINT_LITERAL311=(Token)match(input,FLOATING_POINT_LITERAL,FOLLOW_FLOATING_POINT_LITERAL_in_ftsWordBase8463); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FLOATING_POINT_LITERAL311_tree = (Object)adaptor.create(FLOATING_POINT_LITERAL311); + adaptor.addChild(root_0, FLOATING_POINT_LITERAL311_tree); + } + + } + break; + case 9 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:884:11: STAR + { + root_0 = (Object)adaptor.nil(); + + + STAR312=(Token)match(input,STAR,FOLLOW_STAR_in_ftsWordBase8475); if (state.failed) return retval; + if ( state.backtracking==0 ) { + STAR312_tree = (Object)adaptor.create(STAR312); + adaptor.addChild(root_0, STAR312_tree); + } + + } + break; + case 10 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:885:11: QUESTION_MARK + { + root_0 = (Object)adaptor.nil(); + + + QUESTION_MARK313=(Token)match(input,QUESTION_MARK,FOLLOW_QUESTION_MARK_in_ftsWordBase8487); if (state.failed) return retval; + if ( state.backtracking==0 ) { + QUESTION_MARK313_tree = (Object)adaptor.create(QUESTION_MARK313); + adaptor.addChild(root_0, QUESTION_MARK313_tree); + } + + } + break; + case 11 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:886:11: DATETIME + { + root_0 = (Object)adaptor.nil(); + + + DATETIME314=(Token)match(input,DATETIME,FOLLOW_DATETIME_in_ftsWordBase8499); if (state.failed) return retval; + if ( state.backtracking==0 ) { + DATETIME314_tree = (Object)adaptor.create(DATETIME314); + adaptor.addChild(root_0, DATETIME314_tree); + } + + } + break; + case 12 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:887:11: URI identifier + { + root_0 = (Object)adaptor.nil(); + + + URI315=(Token)match(input,URI,FOLLOW_URI_in_ftsWordBase8511); if (state.failed) return retval; + if ( state.backtracking==0 ) { + URI315_tree = (Object)adaptor.create(URI315); + adaptor.addChild(root_0, URI315_tree); + } + + pushFollow(FOLLOW_identifier_in_ftsWordBase8513); + identifier316=identifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, identifier316.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsWordBase" + + + public static class number_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "number" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:890:1: number : ( DECIMAL_INTEGER_LITERAL | FLOATING_POINT_LITERAL ); + public final FTSParser.number_return number() throws RecognitionException { + FTSParser.number_return retval = new FTSParser.number_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set317=null; + + Object set317_tree=null; + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:891:9: ( DECIMAL_INTEGER_LITERAL | FLOATING_POINT_LITERAL ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + root_0 = (Object)adaptor.nil(); + + + set317=input.LT(1); + if ( input.LA(1)==DECIMAL_INTEGER_LITERAL||input.LA(1)==FLOATING_POINT_LITERAL ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set317)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "number" + + + public static class ftsRangeWord_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "ftsRangeWord" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:896:1: ftsRangeWord : ( ID | FTSWORD | FTSPRE | FTSWILD | FTSPHRASE | DECIMAL_INTEGER_LITERAL | FLOATING_POINT_LITERAL | DATETIME | STAR | URI identifier ); + public final FTSParser.ftsRangeWord_return ftsRangeWord() throws RecognitionException { + FTSParser.ftsRangeWord_return retval = new FTSParser.ftsRangeWord_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token ID318=null; + Token FTSWORD319=null; + Token FTSPRE320=null; + Token FTSWILD321=null; + Token FTSPHRASE322=null; + Token DECIMAL_INTEGER_LITERAL323=null; + Token FLOATING_POINT_LITERAL324=null; + Token DATETIME325=null; + Token STAR326=null; + Token URI327=null; + ParserRuleReturnScope identifier328 =null; + + Object ID318_tree=null; + Object FTSWORD319_tree=null; + Object FTSPRE320_tree=null; + Object FTSWILD321_tree=null; + Object FTSPHRASE322_tree=null; + Object DECIMAL_INTEGER_LITERAL323_tree=null; + Object FLOATING_POINT_LITERAL324_tree=null; + Object DATETIME325_tree=null; + Object STAR326_tree=null; + Object URI327_tree=null; + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:897:9: ( ID | FTSWORD | FTSPRE | FTSWILD | FTSPHRASE | DECIMAL_INTEGER_LITERAL | FLOATING_POINT_LITERAL | DATETIME | STAR | URI identifier ) + int alt75=10; + switch ( input.LA(1) ) { + case ID: + { + alt75=1; + } + break; + case FTSWORD: + { + alt75=2; + } + break; + case FTSPRE: + { + alt75=3; + } + break; + case FTSWILD: + { + alt75=4; + } + break; + case FTSPHRASE: + { + alt75=5; + } + break; + case DECIMAL_INTEGER_LITERAL: + { + alt75=6; + } + break; + case FLOATING_POINT_LITERAL: + { + alt75=7; + } + break; + case DATETIME: + { + alt75=8; + } + break; + case STAR: + { + alt75=9; + } + break; + case URI: + { + alt75=10; + } + break; + default: + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 75, 0, input); + throw nvae; + } + switch (alt75) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:898:11: ID + { + root_0 = (Object)adaptor.nil(); + + + ID318=(Token)match(input,ID,FOLLOW_ID_in_ftsRangeWord8593); if (state.failed) return retval; + if ( state.backtracking==0 ) { + ID318_tree = (Object)adaptor.create(ID318); + adaptor.addChild(root_0, ID318_tree); + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:899:11: FTSWORD + { + root_0 = (Object)adaptor.nil(); + + + FTSWORD319=(Token)match(input,FTSWORD,FOLLOW_FTSWORD_in_ftsRangeWord8605); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FTSWORD319_tree = (Object)adaptor.create(FTSWORD319); + adaptor.addChild(root_0, FTSWORD319_tree); + } + + } + break; + case 3 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:900:11: FTSPRE + { + root_0 = (Object)adaptor.nil(); + + + FTSPRE320=(Token)match(input,FTSPRE,FOLLOW_FTSPRE_in_ftsRangeWord8617); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FTSPRE320_tree = (Object)adaptor.create(FTSPRE320); + adaptor.addChild(root_0, FTSPRE320_tree); + } + + } + break; + case 4 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:901:11: FTSWILD + { + root_0 = (Object)adaptor.nil(); + + + FTSWILD321=(Token)match(input,FTSWILD,FOLLOW_FTSWILD_in_ftsRangeWord8629); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FTSWILD321_tree = (Object)adaptor.create(FTSWILD321); + adaptor.addChild(root_0, FTSWILD321_tree); + } + + } + break; + case 5 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:902:11: FTSPHRASE + { + root_0 = (Object)adaptor.nil(); + + + FTSPHRASE322=(Token)match(input,FTSPHRASE,FOLLOW_FTSPHRASE_in_ftsRangeWord8641); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FTSPHRASE322_tree = (Object)adaptor.create(FTSPHRASE322); + adaptor.addChild(root_0, FTSPHRASE322_tree); + } + + } + break; + case 6 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:903:11: DECIMAL_INTEGER_LITERAL + { + root_0 = (Object)adaptor.nil(); + + + DECIMAL_INTEGER_LITERAL323=(Token)match(input,DECIMAL_INTEGER_LITERAL,FOLLOW_DECIMAL_INTEGER_LITERAL_in_ftsRangeWord8653); if (state.failed) return retval; + if ( state.backtracking==0 ) { + DECIMAL_INTEGER_LITERAL323_tree = (Object)adaptor.create(DECIMAL_INTEGER_LITERAL323); + adaptor.addChild(root_0, DECIMAL_INTEGER_LITERAL323_tree); + } + + } + break; + case 7 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:904:11: FLOATING_POINT_LITERAL + { + root_0 = (Object)adaptor.nil(); + + + FLOATING_POINT_LITERAL324=(Token)match(input,FLOATING_POINT_LITERAL,FOLLOW_FLOATING_POINT_LITERAL_in_ftsRangeWord8665); if (state.failed) return retval; + if ( state.backtracking==0 ) { + FLOATING_POINT_LITERAL324_tree = (Object)adaptor.create(FLOATING_POINT_LITERAL324); + adaptor.addChild(root_0, FLOATING_POINT_LITERAL324_tree); + } + + } + break; + case 8 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:905:11: DATETIME + { + root_0 = (Object)adaptor.nil(); + + + DATETIME325=(Token)match(input,DATETIME,FOLLOW_DATETIME_in_ftsRangeWord8677); if (state.failed) return retval; + if ( state.backtracking==0 ) { + DATETIME325_tree = (Object)adaptor.create(DATETIME325); + adaptor.addChild(root_0, DATETIME325_tree); + } + + } + break; + case 9 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:906:11: STAR + { + root_0 = (Object)adaptor.nil(); + + + STAR326=(Token)match(input,STAR,FOLLOW_STAR_in_ftsRangeWord8689); if (state.failed) return retval; + if ( state.backtracking==0 ) { + STAR326_tree = (Object)adaptor.create(STAR326); + adaptor.addChild(root_0, STAR326_tree); + } + + } + break; + case 10 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:907:11: URI identifier + { + root_0 = (Object)adaptor.nil(); + + + URI327=(Token)match(input,URI,FOLLOW_URI_in_ftsRangeWord8701); if (state.failed) return retval; + if ( state.backtracking==0 ) { + URI327_tree = (Object)adaptor.create(URI327); + adaptor.addChild(root_0, URI327_tree); + } + + pushFollow(FOLLOW_identifier_in_ftsRangeWord8703); + identifier328=identifier(); + state._fsp--; + if (state.failed) return retval; + if ( state.backtracking==0 ) adaptor.addChild(root_0, identifier328.getTree()); + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "ftsRangeWord" + + + public static class or_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "or" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:912:1: or : ( OR | BAR BAR ); + public final FTSParser.or_return or() throws RecognitionException { + FTSParser.or_return retval = new FTSParser.or_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token OR329=null; + Token BAR330=null; + Token BAR331=null; + + Object OR329_tree=null; + Object BAR330_tree=null; + Object BAR331_tree=null; + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:913:9: ( OR | BAR BAR ) + int alt76=2; + int LA76_0 = input.LA(1); + if ( (LA76_0==OR) ) { + alt76=1; + } + else if ( (LA76_0==BAR) ) { + alt76=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 76, 0, input); + throw nvae; + } + + switch (alt76) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:914:9: OR + { + root_0 = (Object)adaptor.nil(); + + + OR329=(Token)match(input,OR,FOLLOW_OR_in_or8738); if (state.failed) return retval; + if ( state.backtracking==0 ) { + OR329_tree = (Object)adaptor.create(OR329); + adaptor.addChild(root_0, OR329_tree); + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:915:11: BAR BAR + { + root_0 = (Object)adaptor.nil(); + + + BAR330=(Token)match(input,BAR,FOLLOW_BAR_in_or8750); if (state.failed) return retval; + if ( state.backtracking==0 ) { + BAR330_tree = (Object)adaptor.create(BAR330); + adaptor.addChild(root_0, BAR330_tree); + } + + BAR331=(Token)match(input,BAR,FOLLOW_BAR_in_or8752); if (state.failed) return retval; + if ( state.backtracking==0 ) { + BAR331_tree = (Object)adaptor.create(BAR331); + adaptor.addChild(root_0, BAR331_tree); + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "or" + + + public static class and_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "and" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:918:1: and : ( AND | AMP AMP ); + public final FTSParser.and_return and() throws RecognitionException { + FTSParser.and_return retval = new FTSParser.and_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token AND332=null; + Token AMP333=null; + Token AMP334=null; + + Object AND332_tree=null; + Object AMP333_tree=null; + Object AMP334_tree=null; + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:919:9: ( AND | AMP AMP ) + int alt77=2; + int LA77_0 = input.LA(1); + if ( (LA77_0==AND) ) { + alt77=1; + } + else if ( (LA77_0==AMP) ) { + alt77=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return retval;} + NoViableAltException nvae = + new NoViableAltException("", 77, 0, input); + throw nvae; + } + + switch (alt77) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:920:9: AND + { + root_0 = (Object)adaptor.nil(); + + + AND332=(Token)match(input,AND,FOLLOW_AND_in_and8785); if (state.failed) return retval; + if ( state.backtracking==0 ) { + AND332_tree = (Object)adaptor.create(AND332); + adaptor.addChild(root_0, AND332_tree); + } + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:921:11: AMP AMP + { + root_0 = (Object)adaptor.nil(); + + + AMP333=(Token)match(input,AMP,FOLLOW_AMP_in_and8797); if (state.failed) return retval; + if ( state.backtracking==0 ) { + AMP333_tree = (Object)adaptor.create(AMP333); + adaptor.addChild(root_0, AMP333_tree); + } + + AMP334=(Token)match(input,AMP,FOLLOW_AMP_in_and8799); if (state.failed) return retval; + if ( state.backtracking==0 ) { + AMP334_tree = (Object)adaptor.create(AMP334); + adaptor.addChild(root_0, AMP334_tree); + } + + } + break; + + } + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "and" + + + public static class not_return extends ParserRuleReturnScope { + Object tree; + @Override + public Object getTree() { return tree; } + }; + + + // $ANTLR start "not" + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:924:1: not : ( NOT | EXCLAMATION ); + public final FTSParser.not_return not() throws RecognitionException { + FTSParser.not_return retval = new FTSParser.not_return(); + retval.start = input.LT(1); + + Object root_0 = null; + + Token set335=null; + + Object set335_tree=null; + + try { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:925:9: ( NOT | EXCLAMATION ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g: + { + root_0 = (Object)adaptor.nil(); + + + set335=input.LT(1); + if ( input.LA(1)==EXCLAMATION||input.LA(1)==NOT ) { + input.consume(); + if ( state.backtracking==0 ) adaptor.addChild(root_0, (Object)adaptor.create(set335)); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return retval;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + + retval.stop = input.LT(-1); + + if ( state.backtracking==0 ) { + retval.tree = (Object)adaptor.rulePostProcessing(root_0); + adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); + } + } + + catch(RecognitionException e) + { + throw e; + } + + finally { + // do for sure before leaving + } + return retval; + } + // $ANTLR end "not" + + // $ANTLR start synpred1_FTS + public final void synpred1_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:415:9: ( not ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:415:10: not + { + pushFollow(FOLLOW_not_in_synpred1_FTS1233); + not(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred1_FTS + + // $ANTLR start synpred2_FTS + public final void synpred2_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:447:12: ( ftsFieldGroupProximity ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:447:13: ftsFieldGroupProximity + { + pushFollow(FOLLOW_ftsFieldGroupProximity_in_synpred2_FTS1746); + ftsFieldGroupProximity(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred2_FTS + + // $ANTLR start synpred3_FTS + public final void synpred3_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:451:12: ( ftsRange ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:451:13: ftsRange + { + pushFollow(FOLLOW_ftsRange_in_synpred3_FTS1823); + ftsRange(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred3_FTS + + // $ANTLR start synpred4_FTS + public final void synpred4_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:455:12: ( ftsFieldGroup ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:455:13: ftsFieldGroup + { + pushFollow(FOLLOW_ftsFieldGroup_in_synpred4_FTS1902); + ftsFieldGroup(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred4_FTS + + // $ANTLR start synpred5_FTS + public final void synpred5_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:458:12: ( ftsTermOrPhrase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:458:13: ftsTermOrPhrase + { + pushFollow(FOLLOW_ftsTermOrPhrase_in_synpred5_FTS1951); + ftsTermOrPhrase(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred5_FTS + + // $ANTLR start synpred6_FTS + public final void synpred6_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:460:12: ( ftsExactTermOrPhrase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:460:13: ftsExactTermOrPhrase + { + pushFollow(FOLLOW_ftsExactTermOrPhrase_in_synpred6_FTS1980); + ftsExactTermOrPhrase(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred6_FTS + + // $ANTLR start synpred7_FTS + public final void synpred7_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:462:12: ( ftsTokenisedTermOrPhrase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:462:13: ftsTokenisedTermOrPhrase + { + pushFollow(FOLLOW_ftsTokenisedTermOrPhrase_in_synpred7_FTS2010); + ftsTokenisedTermOrPhrase(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred7_FTS + + // $ANTLR start synpred8_FTS + public final void synpred8_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:514:9: ( fieldReference COLON ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:514:10: fieldReference COLON + { + pushFollow(FOLLOW_fieldReference_in_synpred8_FTS2683); + fieldReference(); + state._fsp--; + if (state.failed) return; + + match(input,COLON,FOLLOW_COLON_in_synpred8_FTS2685); if (state.failed) return; + + } + + } + // $ANTLR end synpred8_FTS + + // $ANTLR start synpred9_FTS + public final void synpred9_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:516:28: ( slop ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:516:29: slop + { + pushFollow(FOLLOW_slop_in_synpred9_FTS2724); + slop(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred9_FTS + + // $ANTLR start synpred10_FTS + public final void synpred10_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:519:26: ( fuzzy ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:519:27: fuzzy + { + pushFollow(FOLLOW_fuzzy_in_synpred10_FTS2799); + fuzzy(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred10_FTS + + // $ANTLR start synpred11_FTS + public final void synpred11_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:523:20: ( slop ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:523:21: slop + { + pushFollow(FOLLOW_slop_in_synpred11_FTS2869); + slop(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred11_FTS + + // $ANTLR start synpred12_FTS + public final void synpred12_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:526:18: ( fuzzy ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:526:19: fuzzy + { + pushFollow(FOLLOW_fuzzy_in_synpred12_FTS2927); + fuzzy(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred12_FTS + + // $ANTLR start synpred13_FTS + public final void synpred13_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:535:9: ( fieldReference COLON ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:535:10: fieldReference COLON + { + pushFollow(FOLLOW_fieldReference_in_synpred13_FTS3032); + fieldReference(); + state._fsp--; + if (state.failed) return; + + match(input,COLON,FOLLOW_COLON_in_synpred13_FTS3034); if (state.failed) return; + + } + + } + // $ANTLR end synpred13_FTS + + // $ANTLR start synpred14_FTS + public final void synpred14_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:537:28: ( slop ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:537:29: slop + { + pushFollow(FOLLOW_slop_in_synpred14_FTS3073); + slop(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred14_FTS + + // $ANTLR start synpred15_FTS + public final void synpred15_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:540:26: ( fuzzy ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:540:27: fuzzy + { + pushFollow(FOLLOW_fuzzy_in_synpred15_FTS3148); + fuzzy(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred15_FTS + + // $ANTLR start synpred16_FTS + public final void synpred16_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:544:20: ( slop ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:544:21: slop + { + pushFollow(FOLLOW_slop_in_synpred16_FTS3218); + slop(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred16_FTS + + // $ANTLR start synpred17_FTS + public final void synpred17_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:547:18: ( fuzzy ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:547:19: fuzzy + { + pushFollow(FOLLOW_fuzzy_in_synpred17_FTS3276); + fuzzy(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred17_FTS + + // $ANTLR start synpred18_FTS + public final void synpred18_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:557:9: ( fieldReference COLON ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:557:10: fieldReference COLON + { + pushFollow(FOLLOW_fieldReference_in_synpred18_FTS3383); + fieldReference(); + state._fsp--; + if (state.failed) return; + + match(input,COLON,FOLLOW_COLON_in_synpred18_FTS3385); if (state.failed) return; + + } + + } + // $ANTLR end synpred18_FTS + + // $ANTLR start synpred19_FTS + public final void synpred19_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:559:28: ( slop ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:559:29: slop + { + pushFollow(FOLLOW_slop_in_synpred19_FTS3424); + slop(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred19_FTS + + // $ANTLR start synpred20_FTS + public final void synpred20_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:562:26: ( fuzzy ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:562:27: fuzzy + { + pushFollow(FOLLOW_fuzzy_in_synpred20_FTS3499); + fuzzy(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred20_FTS + + // $ANTLR start synpred21_FTS + public final void synpred21_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:566:20: ( slop ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:566:21: slop + { + pushFollow(FOLLOW_slop_in_synpred21_FTS3569); + slop(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred21_FTS + + // $ANTLR start synpred22_FTS + public final void synpred22_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:569:18: ( fuzzy ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:569:19: fuzzy + { + pushFollow(FOLLOW_fuzzy_in_synpred22_FTS3627); + fuzzy(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred22_FTS + + // $ANTLR start synpred23_FTS + public final void synpred23_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:642:9: ( not ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:642:10: not + { + pushFollow(FOLLOW_not_in_synpred23_FTS4374); + not(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred23_FTS + + // $ANTLR start synpred24_FTS + public final void synpred24_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:661:9: ( ftsFieldGroupProximity ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:661:10: ftsFieldGroupProximity + { + pushFollow(FOLLOW_ftsFieldGroupProximity_in_synpred24_FTS4739); + ftsFieldGroupProximity(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred24_FTS + + // $ANTLR start synpred25_FTS + public final void synpred25_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:664:11: ( ftsFieldGroupTerm ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:664:12: ftsFieldGroupTerm + { + pushFollow(FOLLOW_ftsFieldGroupTerm_in_synpred25_FTS4805); + ftsFieldGroupTerm(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred25_FTS + + // $ANTLR start synpred26_FTS + public final void synpred26_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:664:54: ( fuzzy ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:664:55: fuzzy + { + pushFollow(FOLLOW_fuzzy_in_synpred26_FTS4815); + fuzzy(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred26_FTS + + // $ANTLR start synpred27_FTS + public final void synpred27_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:667:11: ( ftsFieldGroupExactTerm ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:667:12: ftsFieldGroupExactTerm + { + pushFollow(FOLLOW_ftsFieldGroupExactTerm_in_synpred27_FTS4886); + ftsFieldGroupExactTerm(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred27_FTS + + // $ANTLR start synpred28_FTS + public final void synpred28_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:667:64: ( fuzzy ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:667:65: fuzzy + { + pushFollow(FOLLOW_fuzzy_in_synpred28_FTS4896); + fuzzy(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred28_FTS + + // $ANTLR start synpred29_FTS + public final void synpred29_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:670:11: ( ftsFieldGroupPhrase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:670:12: ftsFieldGroupPhrase + { + pushFollow(FOLLOW_ftsFieldGroupPhrase_in_synpred29_FTS4967); + ftsFieldGroupPhrase(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred29_FTS + + // $ANTLR start synpred30_FTS + public final void synpred30_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:670:58: ( slop ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:670:59: slop + { + pushFollow(FOLLOW_slop_in_synpred30_FTS4977); + slop(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred30_FTS + + // $ANTLR start synpred31_FTS + public final void synpred31_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:673:11: ( ftsFieldGroupExactPhrase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:673:12: ftsFieldGroupExactPhrase + { + pushFollow(FOLLOW_ftsFieldGroupExactPhrase_in_synpred31_FTS5048); + ftsFieldGroupExactPhrase(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred31_FTS + + // $ANTLR start synpred32_FTS + public final void synpred32_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:673:68: ( slop ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:673:69: slop + { + pushFollow(FOLLOW_slop_in_synpred32_FTS5058); + slop(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred32_FTS + + // $ANTLR start synpred33_FTS + public final void synpred33_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:676:11: ( ftsFieldGroupTokenisedPhrase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:676:12: ftsFieldGroupTokenisedPhrase + { + pushFollow(FOLLOW_ftsFieldGroupTokenisedPhrase_in_synpred33_FTS5129); + ftsFieldGroupTokenisedPhrase(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred33_FTS + + // $ANTLR start synpred34_FTS + public final void synpred34_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:676:76: ( slop ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:676:77: slop + { + pushFollow(FOLLOW_slop_in_synpred34_FTS5139); + slop(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred34_FTS + + // $ANTLR start synpred35_FTS + public final void synpred35_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:679:11: ( ftsFieldGroupSynonym ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:679:12: ftsFieldGroupSynonym + { + pushFollow(FOLLOW_ftsFieldGroupSynonym_in_synpred35_FTS5210); + ftsFieldGroupSynonym(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred35_FTS + + // $ANTLR start synpred36_FTS + public final void synpred36_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:679:60: ( fuzzy ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:679:61: fuzzy + { + pushFollow(FOLLOW_fuzzy_in_synpred36_FTS5220); + fuzzy(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred36_FTS + + // $ANTLR start synpred37_FTS + public final void synpred37_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:682:11: ( ftsFieldGroupRange ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:682:12: ftsFieldGroupRange + { + pushFollow(FOLLOW_ftsFieldGroupRange_in_synpred37_FTS5291); + ftsFieldGroupRange(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred37_FTS + + // $ANTLR start synpred38_FTS + public final void synpred38_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:725:38: ( proximityGroup ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:725:39: proximityGroup + { + pushFollow(FOLLOW_proximityGroup_in_synpred38_FTS5720); + proximityGroup(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred38_FTS + + // $ANTLR start synpred39_FTS + public final void synpred39_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:781:19: ( prefix ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:781:20: prefix + { + pushFollow(FOLLOW_prefix_in_synpred39_FTS6352); + prefix(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred39_FTS + + // $ANTLR start synpred40_FTS + public final void synpred40_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:817:9: ( ID DOT ID ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:817:10: ID DOT ID + { + match(input,ID,FOLLOW_ID_in_synpred40_FTS6807); if (state.failed) return; + + match(input,DOT,FOLLOW_DOT_in_synpred40_FTS6809); if (state.failed) return; + + match(input,ID,FOLLOW_ID_in_synpred40_FTS6811); if (state.failed) return; + + } + + } + // $ANTLR end synpred40_FTS + + // $ANTLR start synpred41_FTS + public final void synpred41_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:837:12: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:837:13: ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase + { + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred41_FTS7133); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred41_FTS7141); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred41_FTS7149); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred41_FTS7157); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred41_FTS7165); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred41_FTS + + // $ANTLR start synpred42_FTS + public final void synpred42_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:839:11: ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase DOT | COMMA ftsWordBase ) + int alt78=2; + int LA78_0 = input.LA(1); + if ( (LA78_0==DATETIME||LA78_0==DECIMAL_INTEGER_LITERAL||LA78_0==FLOATING_POINT_LITERAL||(LA78_0 >= FTSPRE && LA78_0 <= FTSWORD)||LA78_0==ID||LA78_0==NOT||LA78_0==QUESTION_MARK||LA78_0==STAR||LA78_0==TO||LA78_0==URI) ) { + alt78=1; + } + else if ( (LA78_0==COMMA) ) { + alt78=2; + } + + else { + if (state.backtracking>0) {state.failed=true; return;} + NoViableAltException nvae = + new NoViableAltException("", 78, 0, input); + throw nvae; + } + + switch (alt78) { + case 1 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:839:12: ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase DOT + { + pushFollow(FOLLOW_ftsWordBase_in_synpred42_FTS7233); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred42_FTS7241); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred42_FTS7249); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred42_FTS7257); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + match(input,DOT,FOLLOW_DOT_in_synpred42_FTS7259); if (state.failed) return; + + } + break; + case 2 : + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:839:100: COMMA ftsWordBase + { + match(input,COMMA,FOLLOW_COMMA_in_synpred42_FTS7261); if (state.failed) return; + + pushFollow(FOLLOW_ftsWordBase_in_synpred42_FTS7263); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + } + break; + + } + } + // $ANTLR end synpred42_FTS + + // $ANTLR start synpred43_FTS + public final void synpred43_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:841:12: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:841:13: ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) + { + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred43_FTS7332); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred43_FTS7340); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred43_FTS7348); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred43_FTS7356); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + + } + // $ANTLR end synpred43_FTS + + // $ANTLR start synpred44_FTS + public final void synpred44_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:843:11: ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:843:12: ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) + { + pushFollow(FOLLOW_ftsWordBase_in_synpred44_FTS7428); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred44_FTS7436); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred44_FTS7444); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred44_FTS7452); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + + } + // $ANTLR end synpred44_FTS + + // $ANTLR start synpred45_FTS + public final void synpred45_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:845:12: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:845:13: ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase + { + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred45_FTS7525); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred45_FTS7533); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred45_FTS7541); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred45_FTS7549); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred45_FTS + + // $ANTLR start synpred46_FTS + public final void synpred46_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:847:11: ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:847:12: ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase + { + pushFollow(FOLLOW_ftsWordBase_in_synpred46_FTS7609); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred46_FTS7617); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred46_FTS7625); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred46_FTS7633); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred46_FTS + + // $ANTLR start synpred47_FTS + public final void synpred47_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:849:11: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:849:12: ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) + { + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred47_FTS7693); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred47_FTS7701); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred47_FTS7709); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + + } + // $ANTLR end synpred47_FTS + + // $ANTLR start synpred48_FTS + public final void synpred48_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:851:11: ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:851:12: ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) + { + pushFollow(FOLLOW_ftsWordBase_in_synpred48_FTS7773); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred48_FTS7781); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred48_FTS7789); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + + } + // $ANTLR end synpred48_FTS + + // $ANTLR start synpred49_FTS + public final void synpred49_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:853:11: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:853:12: ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase + { + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred49_FTS7853); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred49_FTS7861); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred49_FTS7869); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred49_FTS + + // $ANTLR start synpred50_FTS + public final void synpred50_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:855:11: ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:855:12: ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase + { + pushFollow(FOLLOW_ftsWordBase_in_synpred50_FTS7921); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred50_FTS7929); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred50_FTS7937); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred50_FTS + + // $ANTLR start synpred51_FTS + public final void synpred51_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:857:11: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:857:12: ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) + { + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred51_FTS7990); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred51_FTS7998); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + + } + // $ANTLR end synpred51_FTS + + // $ANTLR start synpred52_FTS + public final void synpred52_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:859:11: ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:859:12: ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) + { + pushFollow(FOLLOW_ftsWordBase_in_synpred52_FTS8054); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred52_FTS8062); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + + } + // $ANTLR end synpred52_FTS + + // $ANTLR start synpred53_FTS + public final void synpred53_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:861:11: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:861:12: ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase + { + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred53_FTS8120); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred53_FTS8128); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred53_FTS + + // $ANTLR start synpred54_FTS + public final void synpred54_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:863:11: ( ftsWordBase ( DOT | COMMA ) ftsWordBase ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:863:12: ftsWordBase ( DOT | COMMA ) ftsWordBase + { + pushFollow(FOLLOW_ftsWordBase_in_synpred54_FTS8172); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred54_FTS8180); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + } + + } + // $ANTLR end synpred54_FTS + + // $ANTLR start synpred55_FTS + public final void synpred55_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:865:11: ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:865:12: ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) + { + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + pushFollow(FOLLOW_ftsWordBase_in_synpred55_FTS8224); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + + } + // $ANTLR end synpred55_FTS + + // $ANTLR start synpred56_FTS + public final void synpred56_FTS_fragment() throws RecognitionException { + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:867:11: ( ftsWordBase ( DOT | COMMA ) ) + // W:\\alfresco\\HEAD-BUG-FIX\\root\\projects\\data-model\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g:867:12: ftsWordBase ( DOT | COMMA ) + { + pushFollow(FOLLOW_ftsWordBase_in_synpred56_FTS8272); + ftsWordBase(); + state._fsp--; + if (state.failed) return; + + if ( input.LA(1)==COMMA||input.LA(1)==DOT ) { + input.consume(); + state.errorRecovery=false; + state.failed=false; + } + else { + if (state.backtracking>0) {state.failed=true; return;} + MismatchedSetException mse = new MismatchedSetException(null,input); + throw mse; + } + } + + } + // $ANTLR end synpred56_FTS + + // Delegated rules + + public final boolean synpred18_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred18_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred43_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred43_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred9_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred9_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred26_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred26_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred51_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred51_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred35_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred35_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred27_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred27_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred42_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred42_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred25_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred25_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred44_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred44_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred8_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred8_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred34_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred34_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred52_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred52_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred17_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred17_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred37_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred37_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred24_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred24_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred10_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred10_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred53_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred53_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred7_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred7_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred40_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred40_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred49_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred49_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred19_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred19_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred23_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred23_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred36_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred36_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred6_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred6_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred11_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred11_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred54_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred54_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred41_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred41_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred13_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred13_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred48_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred48_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred21_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred21_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred14_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred14_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred5_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred5_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred55_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred55_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred12_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred12_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred31_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred31_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred38_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred38_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred47_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred47_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred22_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred22_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred39_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred39_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred4_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred4_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred30_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred30_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred56_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred56_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred32_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred32_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred46_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred46_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred29_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred29_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred1_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred1_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred3_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred3_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred16_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred16_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred50_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred50_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred33_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred33_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred20_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred20_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred28_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred28_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred45_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred45_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred2_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred2_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + public final boolean synpred15_FTS() { + state.backtracking++; + int start = input.mark(); + try { + synpred15_FTS_fragment(); // can never throw exception + } catch (RecognitionException re) { + System.err.println("impossible: "+re); + } + boolean success = !state.failed; + input.rewind(start); + state.backtracking--; + state.failed=false; + return success; + } + + + protected DFA17 dfa17 = new DFA17(this); + protected DFA33 dfa33 = new DFA33(this); + protected DFA39 dfa39 = new DFA39(this); + protected DFA60 dfa60 = new DFA60(this); + protected DFA73 dfa73 = new DFA73(this); + static final String DFA17_eotS = + "\u00c8\uffff"; + static final String DFA17_eofS = + "\1\uffff\12\41\4\uffff\1\41\10\uffff\2\41\40\uffff\5\41\46\uffff\2\41"+ + "\2\uffff\11\41\3\uffff\1\41\47\uffff\1\41\3\uffff\5\41\1\uffff\1\41\4"+ + "\uffff\1\41\26\uffff\1\41\4\uffff"; + static final String DFA17_minS = + "\1\5\12\4\2\5\2\12\1\4\10\uffff\2\4\1\5\37\uffff\5\4\3\12\1\5\3\uffff"+ + "\1\0\13\uffff\1\4\12\0\1\5\7\uffff\2\4\2\12\11\4\1\5\2\uffff\1\4\1\13"+ + "\1\77\3\12\1\4\34\uffff\5\0\1\4\3\uffff\5\4\1\0\1\4\2\uffff\1\12\1\77"+ + "\1\4\12\uffff\1\0\13\uffff\1\4\1\12\1\0\1\uffff\1\0"; + static final String DFA17_maxS = + "\13\150\1\146\1\150\2\12\1\150\10\uffff\3\150\37\uffff\5\150\1\25\2\12"+ + "\1\146\3\uffff\1\0\13\uffff\1\150\12\0\1\146\7\uffff\2\150\2\12\11\150"+ + "\1\146\2\uffff\2\150\1\77\1\25\2\12\1\150\34\uffff\5\0\1\150\3\uffff\5"+ + "\150\1\0\1\150\2\uffff\1\12\1\77\1\150\12\uffff\1\0\13\uffff\1\150\1\12"+ + "\1\0\1\uffff\1\0"; + static final String DFA17_acceptS = + "\20\uffff\2\2\2\4\1\5\1\6\1\7\1\10\3\uffff\1\2\36\4\11\uffff\3\4\1\uffff"+ + "\13\4\14\uffff\6\4\1\3\16\uffff\2\4\7\uffff\1\1\33\4\6\uffff\3\4\7\uffff"+ + "\2\4\3\uffff\12\4\1\uffff\13\4\3\uffff\1\4\1\uffff"; + static final String DFA17_specialS = + "\1\75\1\77\1\37\1\44\1\45\1\62\1\54\1\56\1\52\1\66\1\60\4\uffff\1\55\10"+ + "\uffff\1\25\1\43\1\71\37\uffff\1\33\1\10\1\6\1\13\1\20\7\uffff\1\76\13"+ + "\uffff\1\40\1\24\1\22\1\27\1\42\1\47\1\65\1\61\1\73\1\5\1\46\10\uffff"+ + "\1\53\1\63\2\uffff\1\64\1\15\1\12\1\23\1\31\1\30\1\26\1\41\1\36\3\uffff"+ + "\1\4\1\51\4\uffff\1\32\34\uffff\1\57\1\0\1\7\1\21\1\34\1\50\3\uffff\1"+ + "\70\1\67\1\74\1\3\1\2\1\17\1\11\4\uffff\1\14\12\uffff\1\16\13\uffff\1"+ + "\35\1\uffff\1\72\1\uffff\1\1}>"; + static final String[] DFA17_transitionS = { + "\1\16\1\14\4\uffff\1\22\1\uffff\1\11\1\uffff\1\7\5\uffff\1\22\2\uffff"+ + "\1\24\26\uffff\1\10\2\uffff\1\17\1\3\1\4\1\2\11\uffff\1\1\3\uffff\1\26"+ + "\1\20\1\21\10\uffff\1\5\2\uffff\1\15\1\27\5\uffff\1\23\7\uffff\1\12\4"+ + "\uffff\1\25\1\6\1\uffff\1\13", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\32\1\34\1\uffff\1\56\1\uffff\1\54"+ + "\5\uffff\1\30\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff\1"+ + "\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\34\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\34\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\34\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\34\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\34\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\34\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\32\1\34\1\uffff\1\56\1\uffff\1\54"+ + "\5\uffff\1\34\2\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff\1\61\1"+ + "\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71\5\uffff"+ + "\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42\4\uffff"+ + "\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\32\1\34\1\uffff\1\56\1\uffff\1\54"+ + "\5\uffff\1\34\2\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff\1\61\1"+ + "\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71\5\uffff"+ + "\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42\4\uffff"+ + "\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\34\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\34\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\34\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\34\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\34\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\34\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\34\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\34\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\75\71\uffff\1\72\16\uffff\1\76\2\uffff\1\74\24\uffff\1\73", + "\1\16\71\uffff\1\77\16\uffff\1\101\2\uffff\1\15\24\uffff\1\100\1\uffff"+ + "\1\102", + "\1\32", + "\1\32", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\105\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\105\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\104\4\uffff\1\103\1\53\1\uffff\1\57", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\105\1\uffff\1\120\1\uffff"+ + "\1\114\5\uffff\1\105\2\uffff\1\65\2\uffff\1\52\23\uffff\1\115\2\uffff"+ + "\1\61\1\110\1\111\1\107\11\uffff\1\106\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\112\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\117\2\uffff"+ + "\1\42\4\uffff\1\116\4\uffff\1\35\1\113\1\uffff\1\121", + "\1\143\1\142\1\60\1\44\1\uffff\1\141\1\uffff\1\137\1\uffff\1\133\1\uffff"+ + "\1\131\5\uffff\1\137\1\136\1\uffff\1\65\2\uffff\1\52\23\uffff\1\132\2"+ + "\uffff\1\61\1\125\1\126\1\124\11\uffff\1\123\3\uffff\1\122\1\62\1\63"+ + "\2\uffff\1\71\5\uffff\1\127\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1"+ + "\64\2\uffff\1\42\4\uffff\1\134\4\uffff\1\140\1\130\1\uffff\1\135", + "\1\150\5\uffff\1\163\1\uffff\1\160\1\uffff\1\156\5\uffff\1\163\31\uffff"+ + "\1\157\2\uffff\1\155\1\153\1\154\1\152\11\uffff\1\145\3\uffff\1\144\1"+ + "\20\1\21\10\uffff\1\151\2\uffff\1\147\6\uffff\1\164\7\uffff\1\161\5\uffff"+ + "\1\146\1\uffff\1\162", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\166\1\34\1\uffff\1\56\1\uffff\1"+ + "\54\5\uffff\1\165\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\166\1\34\1\uffff\1\56\1\uffff\1"+ + "\54\5\uffff\1\34\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\166\1\34\1\uffff\1\56\1\uffff\1"+ + "\54\5\uffff\1\34\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\166\1\34\1\uffff\1\56\1\uffff\1"+ + "\54\5\uffff\1\34\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\166\1\34\1\uffff\1\56\1\uffff\1"+ + "\54\5\uffff\1\34\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\31\4\uffff\1\35\1\53\1\uffff\1\57", + "\1\32\12\uffff\1\167", + "\1\32", + "\1\32", + "\1\150\71\uffff\1\170\16\uffff\1\172\2\uffff\1\147\24\uffff\1\171", + "", + "", + "", + "\1\uffff", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\u008c\1\u008b\1\u008e\1\u0097\3\uffff\1\175\1\uffff\1\u0087\1\uffff"+ + "\1\173\5\uffff\1\175\2\uffff\1\u0092\2\uffff\1\u008d\23\uffff\1\u0084"+ + "\2\uffff\1\u0089\1\u0080\1\u0081\1\177\11\uffff\1\176\3\uffff\1\u0094"+ + "\1\u0090\1\u0091\2\uffff\1\u008a\5\uffff\1\u0082\2\uffff\1\u008f\1\u0095"+ + "\1\uffff\1\u0096\3\uffff\1\u0086\2\uffff\1\174\4\uffff\1\u0085\4\uffff"+ + "\1\u0093\1\u0083\1\uffff\1\u0088", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\u009b\71\uffff\1\u0098\16\uffff\1\u009c\2\uffff\1\u009a\24\uffff"+ + "\1\u0099", + "", + "", + "", + "", + "", + "", + "", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\166\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009d\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2"+ + "\uffff\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\166\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009e\2\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\166", + "\1\166", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\166\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009e\2\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009e\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2"+ + "\uffff\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009e\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2"+ + "\uffff\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009e\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2"+ + "\uffff\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\105\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\105\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2\uffff"+ + "\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff\1\71"+ + "\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff\1\42"+ + "\4\uffff\1\104\4\uffff\1\u00a0\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009e\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2"+ + "\uffff\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009e\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2"+ + "\uffff\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009e\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2"+ + "\uffff\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009e\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2"+ + "\uffff\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\u00a4\71\uffff\1\u00a1\16\uffff\1\u00a5\2\uffff\1\u00a3\24\uffff"+ + "\1\u00a2", + "", + "", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\105\1\uffff\1\120\1\uffff"+ + "\1\114\5\uffff\1\105\2\uffff\1\65\2\uffff\1\52\23\uffff\1\115\2\uffff"+ + "\1\61\1\110\1\111\1\107\11\uffff\1\u00a6\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\112\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\117\2\uffff"+ + "\1\42\4\uffff\1\116\4\uffff\1\35\1\113\1\uffff\1\121", + "\1\163\1\uffff\1\160\1\uffff\1\156\5\uffff\1\163\31\uffff\1\157\2\uffff"+ + "\1\155\1\153\1\154\1\152\11\uffff\1\u00a7\3\uffff\1\144\1\20\1\21\10"+ + "\uffff\1\u00a8\11\uffff\1\164\7\uffff\1\161\5\uffff\1\u00a9\1\uffff\1"+ + "\162", + "\1\u00aa", + "\1\166\12\uffff\1\u00ab", + "\1\166", + "\1\166", + "\1\u00b6\1\u00b5\1\u008e\1\u00af\1\uffff\1\u00b4\1\uffff\1\u00ad\1\uffff"+ + "\1\u0087\1\uffff\1\u00b0\5\uffff\1\u00ad\1\u00b2\1\uffff\1\u0092\2\uffff"+ + "\1\u008d\23\uffff\1\u0084\2\uffff\1\u0089\1\u0080\1\u0081\1\177\11\uffff"+ + "\1\176\3\uffff\1\u0094\1\u0090\1\u0091\2\uffff\1\u008a\5\uffff\1\u0082"+ + "\2\uffff\1\u00ae\1\u0095\1\uffff\1\u0096\3\uffff\1\u0086\2\uffff\1\u00ac"+ + "\4\uffff\1\u00b1\4\uffff\1\u00b3\1\u0083\1\uffff\1\u0088", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\105\1\uffff\1\u00c1\1\uffff"+ + "\1\u00bd\5\uffff\1\105\2\uffff\1\65\2\uffff\1\52\23\uffff\1\u00be\2\uffff"+ + "\1\61\1\u00b9\1\u00ba\1\u00b8\11\uffff\1\u00b7\3\uffff\1\66\1\62\1\63"+ + "\2\uffff\1\71\5\uffff\1\u00bb\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff"+ + "\1\u00c0\2\uffff\1\42\4\uffff\1\u00bf\4\uffff\1\u009f\1\u00bc\1\uffff"+ + "\1\u00c2", + "", + "", + "", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u00c3\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2"+ + "\uffff\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009e\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2"+ + "\uffff\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009e\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2"+ + "\uffff\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009e\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2"+ + "\uffff\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009e\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2"+ + "\uffff\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "\1\uffff", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\u009e\1\uffff\1\56\1\uffff"+ + "\1\54\5\uffff\1\u009e\1\33\1\uffff\1\65\2\uffff\1\52\23\uffff\1\55\2"+ + "\uffff\1\61\1\50\1\51\1\47\11\uffff\1\46\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\45\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\104\4\uffff\1\u009f\1\53\1\uffff\1\57", + "", + "", + "\1\32", + "\1\u00c4", + "\1\143\1\142\1\60\1\44\1\uffff\1\141\1\uffff\1\105\1\uffff\1\133\1\uffff"+ + "\1\131\5\uffff\1\105\2\uffff\1\65\2\uffff\1\52\23\uffff\1\132\2\uffff"+ + "\1\61\1\125\1\126\1\124\11\uffff\1\123\3\uffff\1\66\1\62\1\63\2\uffff"+ + "\1\71\5\uffff\1\127\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff\1\64\2\uffff"+ + "\1\42\4\uffff\1\u00c5\4\uffff\1\u00c6\1\130\1\uffff\1\135", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\uffff", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\40\1\37\1\60\1\44\1\uffff\1\36\1\uffff\1\105\1\uffff\1\u00c1\1\uffff"+ + "\1\u00bd\5\uffff\1\105\2\uffff\1\65\2\uffff\1\52\23\uffff\1\u00be\2\uffff"+ + "\1\61\1\u00b9\1\u00ba\1\u00b8\11\uffff\1\u00c7\3\uffff\1\66\1\62\1\63"+ + "\2\uffff\1\71\5\uffff\1\u00bb\2\uffff\1\43\1\67\1\uffff\1\70\3\uffff"+ + "\1\u00c0\2\uffff\1\42\4\uffff\1\u00bf\4\uffff\1\u009f\1\u00bc\1\uffff"+ + "\1\u00c2", + "\1\166", + "\1\uffff", + "", + "\1\uffff" + }; + + static final short[] DFA17_eot = DFA.unpackEncodedString(DFA17_eotS); + static final short[] DFA17_eof = DFA.unpackEncodedString(DFA17_eofS); + static final char[] DFA17_min = DFA.unpackEncodedStringToUnsignedChars(DFA17_minS); + static final char[] DFA17_max = DFA.unpackEncodedStringToUnsignedChars(DFA17_maxS); + static final short[] DFA17_accept = DFA.unpackEncodedString(DFA17_acceptS); + static final short[] DFA17_special = DFA.unpackEncodedString(DFA17_specialS); + static final short[][] DFA17_transition; + + static { + int numStates = DFA17_transitionS.length; + DFA17_transition = new short[numStates][]; + for (int i=0; i ftsFieldGroupProximity -> ^( PROXIMITY ftsFieldGroupProximity ) | ( ftsRange )=> ftsRange -> ^( RANGE ftsRange ) | ( ftsFieldGroup )=> ftsFieldGroup -> ftsFieldGroup | ( ftsTermOrPhrase )=> ftsTermOrPhrase | ( ftsExactTermOrPhrase )=> ftsExactTermOrPhrase | ( ftsTokenisedTermOrPhrase )=> ftsTokenisedTermOrPhrase | LPAREN ftsDisjunction RPAREN -> ftsDisjunction | template -> template );"; + } + @Override + public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { + TokenStream input = (TokenStream)_input; + int _s = s; + switch ( s ) { + case 0 : + int LA17_153 = input.LA(1); + + int index17_153 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 182;} + + input.seek(index17_153); + if ( s>=0 ) return s; + break; + + case 1 : + int LA17_199 = input.LA(1); + + int index17_199 = input.index(); + input.rewind(); + s = -1; + if ( (synpred3_FTS()) ) {s = 27;} + else if ( (synpred5_FTS()) ) {s = 198;} + + input.seek(index17_199); + if ( s>=0 ) return s; + break; + + case 2 : + int LA17_165 = input.LA(1); + + int index17_165 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_165==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_165==COMMA||LA17_165==DOT) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_165==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_165==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_165==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_165==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_165==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_165==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_165==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_165==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_165==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_165==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_165==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_165==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_165==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_165==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_165==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_165==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_165==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_165==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_165==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_165==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_165==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_165==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_165==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_165==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_165==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_165==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_165==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_165==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_165==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_165==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_165); + if ( s>=0 ) return s; + break; + + case 3 : + int LA17_164 = input.LA(1); + + int index17_164 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_164==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_164==COMMA||LA17_164==DOT) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_164==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_164==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_164==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_164==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_164==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_164==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_164==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_164==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_164==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_164==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_164==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_164==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_164==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_164==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_164==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_164==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_164==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_164==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_164==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_164==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_164==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_164==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_164==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_164==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_164==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_164==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_164==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_164==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_164==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_164==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_164); + if ( s>=0 ) return s; + break; + + case 4 : + int LA17_117 = input.LA(1); + + int index17_117 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_117==ID) ) {s = 166;} + else if ( (LA17_117==FTSWORD) && (synpred5_FTS())) {s = 71;} + else if ( (LA17_117==FTSPRE) && (synpred5_FTS())) {s = 72;} + else if ( (LA17_117==FTSWILD) && (synpred5_FTS())) {s = 73;} + else if ( (LA17_117==NOT) && (synpred5_FTS())) {s = 74;} + else if ( (LA17_117==TO) && (synpred5_FTS())) {s = 75;} + else if ( (LA17_117==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 76;} + else if ( (LA17_117==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 77;} + else if ( (LA17_117==STAR) && (synpred5_FTS())) {s = 78;} + else if ( (LA17_117==QUESTION_MARK) && (synpred5_FTS())) {s = 79;} + else if ( (LA17_117==DATETIME) && (synpred5_FTS())) {s = 80;} + else if ( (LA17_117==URI) && (synpred5_FTS())) {s = 81;} + else if ( (LA17_117==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_117==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_117==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_117==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_117==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_117==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_117==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_117==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_117==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_117==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_117==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_117==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_117==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_117==COMMA||LA17_117==DOT) && (synpred5_FTS())) {s = 69;} + else if ( (LA17_117==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_117==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_117==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_117==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_117==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_117); + if ( s>=0 ) return s; + break; + + case 5 : + int LA17_91 = input.LA(1); + + int index17_91 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 151;} + + input.seek(index17_91); + if ( s>=0 ) return s; + break; + + case 6 : + int LA17_60 = input.LA(1); + + int index17_60 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_60==STAR) ) {s = 25;} + else if ( (LA17_60==COLON) ) {s = 118;} + else if ( (LA17_60==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_60==COMMA||LA17_60==DOT) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_60==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_60==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_60==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_60==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_60==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_60==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_60==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_60==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_60==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_60==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_60==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_60==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_60==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_60==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_60==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_60==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_60==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_60==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_60==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_60==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_60==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_60==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_60==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_60==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_60==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_60==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_60==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_60==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_60==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_60); + if ( s>=0 ) return s; + break; + + case 7 : + int LA17_154 = input.LA(1); + + int index17_154 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 182;} + + input.seek(index17_154); + if ( s>=0 ) return s; + break; + + case 8 : + int LA17_59 = input.LA(1); + + int index17_59 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_59==STAR) ) {s = 25;} + else if ( (LA17_59==COLON) ) {s = 118;} + else if ( (LA17_59==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_59==COMMA||LA17_59==DOT) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_59==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_59==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_59==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_59==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_59==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_59==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_59==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_59==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_59==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_59==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_59==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_59==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_59==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_59==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_59==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_59==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_59==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_59==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_59==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_59==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_59==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_59==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_59==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_59==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_59==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_59==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_59==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_59==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_59==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_59); + if ( s>=0 ) return s; + break; + + case 9 : + int LA17_167 = input.LA(1); + + int index17_167 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_167==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_167==COMMA||LA17_167==DOT) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_167==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_167==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_167==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_167==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_167==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_167==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_167==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_167==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_167==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_167==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_167==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_167==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_167==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_167==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_167==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_167==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_167==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_167==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_167==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_167==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_167==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_167==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_167==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_167==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_167==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_167==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_167==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_167==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_167==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_167==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_167); + if ( s>=0 ) return s; + break; + + case 10 : + int LA17_107 = input.LA(1); + + int index17_107 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_107==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_107==COMMA||LA17_107==DOT) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_107==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_107==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_107==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_107==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_107==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_107==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_107==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_107==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_107==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_107==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_107==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_107==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_107==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_107==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_107==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_107==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_107==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_107==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_107==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_107==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_107==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_107==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_107==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_107==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_107==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_107==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_107==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_107==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_107==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_107==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_107); + if ( s>=0 ) return s; + break; + + case 11 : + int LA17_61 = input.LA(1); + + int index17_61 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_61==STAR) ) {s = 25;} + else if ( (LA17_61==COLON) ) {s = 118;} + else if ( (LA17_61==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_61==COMMA||LA17_61==DOT) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_61==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_61==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_61==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_61==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_61==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_61==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_61==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_61==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_61==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_61==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_61==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_61==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_61==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_61==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_61==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_61==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_61==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_61==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_61==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_61==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_61==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_61==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_61==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_61==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_61==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_61==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_61==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_61==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_61==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_61); + if ( s>=0 ) return s; + break; + + case 12 : + int LA17_172 = input.LA(1); + + int index17_172 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_172==ID) ) {s = 83;} + else if ( (LA17_172==FTSWORD) ) {s = 84;} + else if ( (LA17_172==FTSPRE) ) {s = 85;} + else if ( (LA17_172==FTSWILD) ) {s = 86;} + else if ( (LA17_172==NOT) ) {s = 87;} + else if ( (LA17_172==TO) ) {s = 88;} + else if ( (LA17_172==DECIMAL_INTEGER_LITERAL) ) {s = 89;} + else if ( (LA17_172==FLOATING_POINT_LITERAL) ) {s = 90;} + else if ( (LA17_172==DATETIME) ) {s = 91;} + else if ( (LA17_172==STAR) ) {s = 197;} + else if ( (LA17_172==URI) ) {s = 93;} + else if ( (LA17_172==CARAT) && (synpred5_FTS())) {s = 97;} + else if ( (LA17_172==AND) && (synpred5_FTS())) {s = 98;} + else if ( (LA17_172==AMP) && (synpred5_FTS())) {s = 99;} + else if ( (LA17_172==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_172==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_172==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_172==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_172==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_172==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_172==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_172==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_172==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_172==COMMA||LA17_172==DOT) && (synpred5_FTS())) {s = 69;} + else if ( (LA17_172==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_172==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_172==TILDA) && (synpred5_FTS())) {s = 198;} + else if ( (LA17_172==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_172==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_172==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_172==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_172); + if ( s>=0 ) return s; + break; + + case 13 : + int LA17_106 = input.LA(1); + + int index17_106 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_106==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_106==COMMA||LA17_106==DOT) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_106==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_106==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_106==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_106==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_106==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_106==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_106==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_106==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_106==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_106==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_106==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_106==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_106==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_106==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_106==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_106==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_106==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_106==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_106==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_106==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_106==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_106==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_106==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_106==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_106==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_106==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_106==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_106==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_106==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_106==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_106); + if ( s>=0 ) return s; + break; + + case 14 : + int LA17_183 = input.LA(1); + + int index17_183 = input.index(); + input.rewind(); + s = -1; + if ( (synpred3_FTS()) ) {s = 27;} + else if ( (synpred4_FTS()) ) {s = 100;} + else if ( (synpred5_FTS()) ) {s = 198;} + + input.seek(index17_183); + if ( s>=0 ) return s; + break; + + case 15 : + int LA17_166 = input.LA(1); + + int index17_166 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred3_FTS()) ) {s = 27;} + else if ( (synpred4_FTS()) ) {s = 100;} + else if ( (synpred5_FTS()) ) {s = 194;} + + input.seek(index17_166); + if ( s>=0 ) return s; + break; + + case 16 : + int LA17_62 = input.LA(1); + + int index17_62 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_62==STAR) ) {s = 25;} + else if ( (LA17_62==COLON) ) {s = 118;} + else if ( (LA17_62==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_62==COMMA||LA17_62==DOT) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_62==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_62==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_62==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_62==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_62==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_62==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_62==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_62==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_62==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_62==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_62==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_62==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_62==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_62==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_62==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_62==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_62==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_62==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_62==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_62==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_62==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_62==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_62==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_62==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_62==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_62==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_62==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_62==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_62==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_62); + if ( s>=0 ) return s; + break; + + case 17 : + int LA17_155 = input.LA(1); + + int index17_155 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 182;} + + input.seek(index17_155); + if ( s>=0 ) return s; + break; + + case 18 : + int LA17_84 = input.LA(1); + + int index17_84 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 151;} + + input.seek(index17_84); + if ( s>=0 ) return s; + break; + + case 19 : + int LA17_108 = input.LA(1); + + int index17_108 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_108==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_108==COMMA||LA17_108==DOT) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_108==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_108==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_108==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_108==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_108==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_108==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_108==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_108==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_108==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_108==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_108==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_108==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_108==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_108==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_108==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_108==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_108==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_108==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_108==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_108==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_108==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_108==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_108==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_108==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_108==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_108==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_108==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_108==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_108==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_108==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_108); + if ( s>=0 ) return s; + break; + + case 20 : + int LA17_83 = input.LA(1); + + int index17_83 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 151;} + + input.seek(index17_83); + if ( s>=0 ) return s; + break; + + case 21 : + int LA17_24 = input.LA(1); + + int index17_24 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_24==ID) ) {s = 70;} + else if ( (LA17_24==FTSWORD) && (synpred5_FTS())) {s = 71;} + else if ( (LA17_24==FTSPRE) && (synpred5_FTS())) {s = 72;} + else if ( (LA17_24==FTSWILD) && (synpred5_FTS())) {s = 73;} + else if ( (LA17_24==NOT) && (synpred5_FTS())) {s = 74;} + else if ( (LA17_24==TO) && (synpred5_FTS())) {s = 75;} + else if ( (LA17_24==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 76;} + else if ( (LA17_24==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 77;} + else if ( (LA17_24==STAR) && (synpred5_FTS())) {s = 78;} + else if ( (LA17_24==QUESTION_MARK) && (synpred5_FTS())) {s = 79;} + else if ( (LA17_24==DATETIME) && (synpred5_FTS())) {s = 80;} + else if ( (LA17_24==URI) && (synpred5_FTS())) {s = 81;} + else if ( (LA17_24==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_24==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_24==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_24==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_24==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_24==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_24==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_24==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_24==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_24==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_24==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_24==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_24==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_24==COMMA||LA17_24==DOT) && (synpred5_FTS())) {s = 69;} + else if ( (LA17_24==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_24==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_24==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_24==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_24==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_24); + if ( s>=0 ) return s; + break; + + case 22 : + int LA17_111 = input.LA(1); + + int index17_111 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_111==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_111==COMMA||LA17_111==DOT) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_111==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_111==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_111==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_111==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_111==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_111==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_111==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_111==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_111==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_111==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_111==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_111==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_111==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_111==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_111==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_111==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_111==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_111==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_111==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_111==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_111==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_111==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_111==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_111==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_111==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_111==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_111==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_111==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_111==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_111==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_111); + if ( s>=0 ) return s; + break; + + case 23 : + int LA17_85 = input.LA(1); + + int index17_85 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 151;} + + input.seek(index17_85); + if ( s>=0 ) return s; + break; + + case 24 : + int LA17_110 = input.LA(1); + + int index17_110 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_110==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_110==COMMA||LA17_110==DOT) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_110==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_110==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_110==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_110==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_110==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_110==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_110==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_110==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_110==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_110==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_110==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_110==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_110==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_110==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_110==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_110==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_110==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_110==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_110==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_110==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_110==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_110==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_110==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_110==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_110==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_110==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_110==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_110==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_110==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_110==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_110); + if ( s>=0 ) return s; + break; + + case 25 : + int LA17_109 = input.LA(1); + + int index17_109 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_109==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_109==TILDA) && (synpred5_FTS())) {s = 160;} + else if ( (LA17_109==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_109==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_109==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_109==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_109==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_109==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_109==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_109==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_109==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_109==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_109==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_109==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_109==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_109==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_109==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_109==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_109==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_109==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_109==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_109==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_109==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_109==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_109==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_109==COMMA||LA17_109==DOT) && (synpred5_FTS())) {s = 69;} + else if ( (LA17_109==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_109==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_109==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_109==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_109==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_109==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_109); + if ( s>=0 ) return s; + break; + + case 26 : + int LA17_123 = input.LA(1); + + int index17_123 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_123==RPAREN) ) {s = 172;} + else if ( (LA17_123==COMMA||LA17_123==DOT) && (synpred5_FTS())) {s = 173;} + else if ( (LA17_123==OR) && (synpred5_FTS())) {s = 174;} + else if ( (LA17_123==BAR) && (synpred5_FTS())) {s = 175;} + else if ( (LA17_123==ID) && (synpred5_FTS())) {s = 126;} + else if ( (LA17_123==FTSWORD) && (synpred5_FTS())) {s = 127;} + else if ( (LA17_123==FTSPRE) && (synpred5_FTS())) {s = 128;} + else if ( (LA17_123==FTSWILD) && (synpred5_FTS())) {s = 129;} + else if ( (LA17_123==NOT) && (synpred5_FTS())) {s = 130;} + else if ( (LA17_123==TO) && (synpred5_FTS())) {s = 131;} + else if ( (LA17_123==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 176;} + else if ( (LA17_123==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 132;} + else if ( (LA17_123==STAR) && (synpred5_FTS())) {s = 177;} + else if ( (LA17_123==QUESTION_MARK) && (synpred5_FTS())) {s = 134;} + else if ( (LA17_123==DATETIME) && (synpred5_FTS())) {s = 135;} + else if ( (LA17_123==URI) && (synpred5_FTS())) {s = 136;} + else if ( (LA17_123==FTSPHRASE) && (synpred5_FTS())) {s = 137;} + else if ( (LA17_123==MINUS) && (synpred5_FTS())) {s = 138;} + else if ( (LA17_123==DOTDOT) && (synpred5_FTS())) {s = 178;} + else if ( (LA17_123==TILDA) && (synpred5_FTS())) {s = 179;} + else if ( (LA17_123==CARAT) && (synpred5_FTS())) {s = 180;} + else if ( (LA17_123==AND) && (synpred5_FTS())) {s = 181;} + else if ( (LA17_123==AMP) && (synpred5_FTS())) {s = 182;} + else if ( (LA17_123==EXCLAMATION) && (synpred5_FTS())) {s = 141;} + else if ( (LA17_123==AT) && (synpred5_FTS())) {s = 142;} + else if ( (LA17_123==LSQUARE) && (synpred5_FTS())) {s = 144;} + else if ( (LA17_123==LT) && (synpred5_FTS())) {s = 145;} + else if ( (LA17_123==EQUALS) && (synpred5_FTS())) {s = 146;} + else if ( (LA17_123==LPAREN) && (synpred5_FTS())) {s = 148;} + else if ( (LA17_123==PERCENT) && (synpred5_FTS())) {s = 149;} + else if ( (LA17_123==PLUS) && (synpred5_FTS())) {s = 150;} + + input.seek(index17_123); + if ( s>=0 ) return s; + break; + + case 27 : + int LA17_58 = input.LA(1); + + int index17_58 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_58==DOT) ) {s = 117;} + else if ( (LA17_58==STAR) ) {s = 25;} + else if ( (LA17_58==COLON) ) {s = 118;} + else if ( (LA17_58==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_58==COMMA) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_58==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_58==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_58==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_58==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_58==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_58==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_58==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_58==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_58==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_58==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_58==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_58==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_58==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_58==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_58==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_58==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_58==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_58==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_58==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_58==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_58==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_58==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_58==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_58==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_58==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_58==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_58==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_58==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_58==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_58); + if ( s>=0 ) return s; + break; + + case 28 : + int LA17_156 = input.LA(1); + + int index17_156 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 182;} + + input.seek(index17_156); + if ( s>=0 ) return s; + break; + + case 29 : + int LA17_195 = input.LA(1); + + int index17_195 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_195==ID) ) {s = 199;} + else if ( (LA17_195==FTSWORD) && (synpred5_FTS())) {s = 184;} + else if ( (LA17_195==FTSPRE) && (synpred5_FTS())) {s = 185;} + else if ( (LA17_195==FTSWILD) && (synpred5_FTS())) {s = 186;} + else if ( (LA17_195==NOT) && (synpred5_FTS())) {s = 187;} + else if ( (LA17_195==TO) && (synpred5_FTS())) {s = 188;} + else if ( (LA17_195==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 189;} + else if ( (LA17_195==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 190;} + else if ( (LA17_195==STAR) && (synpred5_FTS())) {s = 191;} + else if ( (LA17_195==QUESTION_MARK) && (synpred5_FTS())) {s = 192;} + else if ( (LA17_195==DATETIME) && (synpred5_FTS())) {s = 193;} + else if ( (LA17_195==URI) && (synpred5_FTS())) {s = 194;} + else if ( (LA17_195==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_195==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_195==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_195==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_195==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_195==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_195==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_195==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_195==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_195==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_195==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_195==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_195==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_195==COMMA||LA17_195==DOT) && (synpred5_FTS())) {s = 69;} + else if ( (LA17_195==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_195==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_195==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_195==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_195==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_195); + if ( s>=0 ) return s; + break; + + case 30 : + int LA17_113 = input.LA(1); + + int index17_113 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_113==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_113==COMMA||LA17_113==DOT) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_113==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_113==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_113==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_113==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_113==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_113==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_113==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_113==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_113==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_113==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_113==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_113==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_113==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_113==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_113==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_113==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_113==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_113==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_113==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_113==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_113==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_113==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_113==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_113==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_113==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_113==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_113==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_113==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_113==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_113==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_113); + if ( s>=0 ) return s; + break; + + case 31 : + int LA17_2 = input.LA(1); + + int index17_2 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_2==STAR) ) {s = 25;} + else if ( (LA17_2==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_2==COMMA||LA17_2==DOT) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_2==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_2==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_2==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_2==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_2==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_2==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_2==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_2==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_2==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_2==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_2==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_2==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_2==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_2==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_2==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_2==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_2==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_2==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_2==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_2==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_2==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_2==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_2==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_2==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_2==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_2==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_2==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_2==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_2==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_2); + if ( s>=0 ) return s; + break; + + case 32 : + int LA17_82 = input.LA(1); + + int index17_82 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_82==DECIMAL_INTEGER_LITERAL) ) {s = 123;} + else if ( (LA17_82==RPAREN) && (synpred2_FTS())) {s = 124;} + else if ( (LA17_82==COMMA||LA17_82==DOT) && (synpred5_FTS())) {s = 125;} + else if ( (LA17_82==ID) && (synpred5_FTS())) {s = 126;} + else if ( (LA17_82==FTSWORD) && (synpred5_FTS())) {s = 127;} + else if ( (LA17_82==FTSPRE) && (synpred5_FTS())) {s = 128;} + else if ( (LA17_82==FTSWILD) && (synpred5_FTS())) {s = 129;} + else if ( (LA17_82==NOT) && (synpred5_FTS())) {s = 130;} + else if ( (LA17_82==TO) && (synpred5_FTS())) {s = 131;} + else if ( (LA17_82==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 132;} + else if ( (LA17_82==STAR) && (synpred5_FTS())) {s = 133;} + else if ( (LA17_82==QUESTION_MARK) && (synpred5_FTS())) {s = 134;} + else if ( (LA17_82==DATETIME) && (synpred5_FTS())) {s = 135;} + else if ( (LA17_82==URI) && (synpred5_FTS())) {s = 136;} + else if ( (LA17_82==FTSPHRASE) && (synpred5_FTS())) {s = 137;} + else if ( (LA17_82==MINUS) && (synpred5_FTS())) {s = 138;} + else if ( (LA17_82==AND) && (synpred5_FTS())) {s = 139;} + else if ( (LA17_82==AMP) && (synpred5_FTS())) {s = 140;} + else if ( (LA17_82==EXCLAMATION) && (synpred5_FTS())) {s = 141;} + else if ( (LA17_82==AT) && (synpred5_FTS())) {s = 142;} + else if ( (LA17_82==OR) && (synpred5_FTS())) {s = 143;} + else if ( (LA17_82==LSQUARE) && (synpred5_FTS())) {s = 144;} + else if ( (LA17_82==LT) && (synpred5_FTS())) {s = 145;} + else if ( (LA17_82==EQUALS) && (synpred5_FTS())) {s = 146;} + else if ( (LA17_82==TILDA) && (synpred5_FTS())) {s = 147;} + else if ( (LA17_82==LPAREN) && (synpred5_FTS())) {s = 148;} + else if ( (LA17_82==PERCENT) && (synpred5_FTS())) {s = 149;} + else if ( (LA17_82==PLUS) && (synpred5_FTS())) {s = 150;} + else if ( (LA17_82==BAR) && (synpred5_FTS())) {s = 151;} + + input.seek(index17_82); + if ( s>=0 ) return s; + break; + + case 33 : + int LA17_112 = input.LA(1); + + int index17_112 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_112==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_112==COMMA||LA17_112==DOT) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_112==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_112==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_112==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_112==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_112==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_112==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_112==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_112==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_112==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_112==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_112==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_112==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_112==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_112==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_112==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_112==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_112==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_112==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_112==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_112==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_112==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_112==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_112==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_112==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_112==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_112==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_112==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_112==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_112==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_112==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_112); + if ( s>=0 ) return s; + break; + + case 34 : + int LA17_86 = input.LA(1); + + int index17_86 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 151;} + + input.seek(index17_86); + if ( s>=0 ) return s; + break; + + case 35 : + int LA17_25 = input.LA(1); + + int index17_25 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_25==LPAREN) ) {s = 82;} + else if ( (LA17_25==ID) ) {s = 83;} + else if ( (LA17_25==FTSWORD) ) {s = 84;} + else if ( (LA17_25==FTSPRE) ) {s = 85;} + else if ( (LA17_25==FTSWILD) ) {s = 86;} + else if ( (LA17_25==NOT) ) {s = 87;} + else if ( (LA17_25==TO) ) {s = 88;} + else if ( (LA17_25==DECIMAL_INTEGER_LITERAL) ) {s = 89;} + else if ( (LA17_25==FLOATING_POINT_LITERAL) ) {s = 90;} + else if ( (LA17_25==DATETIME) ) {s = 91;} + else if ( (LA17_25==STAR) ) {s = 92;} + else if ( (LA17_25==URI) ) {s = 93;} + else if ( (LA17_25==DOTDOT) && (synpred5_FTS())) {s = 94;} + else if ( (LA17_25==COMMA||LA17_25==DOT) && (synpred5_FTS())) {s = 95;} + else if ( (LA17_25==TILDA) && (synpred5_FTS())) {s = 96;} + else if ( (LA17_25==CARAT) && (synpred5_FTS())) {s = 97;} + else if ( (LA17_25==AND) && (synpred5_FTS())) {s = 98;} + else if ( (LA17_25==AMP) && (synpred5_FTS())) {s = 99;} + else if ( (LA17_25==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_25==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_25==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_25==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_25==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_25==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_25==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_25==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_25==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_25==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_25==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_25==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_25==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_25==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_25); + if ( s>=0 ) return s; + break; + + case 36 : + int LA17_3 = input.LA(1); + + int index17_3 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_3==STAR) ) {s = 25;} + else if ( (LA17_3==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_3==COMMA||LA17_3==DOT) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_3==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_3==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_3==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_3==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_3==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_3==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_3==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_3==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_3==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_3==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_3==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_3==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_3==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_3==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_3==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_3==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_3==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_3==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_3==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_3==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_3==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_3==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_3==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_3==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_3==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_3==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_3==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_3==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_3==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_3); + if ( s>=0 ) return s; + break; + + case 37 : + int LA17_4 = input.LA(1); + + int index17_4 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_4==STAR) ) {s = 25;} + else if ( (LA17_4==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_4==COMMA||LA17_4==DOT) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_4==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_4==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_4==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_4==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_4==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_4==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_4==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_4==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_4==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_4==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_4==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_4==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_4==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_4==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_4==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_4==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_4==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_4==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_4==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_4==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_4==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_4==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_4==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_4==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_4==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_4==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_4==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_4==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_4==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_4); + if ( s>=0 ) return s; + break; + + case 38 : + int LA17_92 = input.LA(1); + + int index17_92 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 151;} + + input.seek(index17_92); + if ( s>=0 ) return s; + break; + + case 39 : + int LA17_87 = input.LA(1); + + int index17_87 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 151;} + + input.seek(index17_87); + if ( s>=0 ) return s; + break; + + case 40 : + int LA17_157 = input.LA(1); + + int index17_157 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_157==ID) ) {s = 183;} + else if ( (LA17_157==FTSWORD) && (synpred5_FTS())) {s = 184;} + else if ( (LA17_157==FTSPRE) && (synpred5_FTS())) {s = 185;} + else if ( (LA17_157==FTSWILD) && (synpred5_FTS())) {s = 186;} + else if ( (LA17_157==NOT) && (synpred5_FTS())) {s = 187;} + else if ( (LA17_157==TO) && (synpred5_FTS())) {s = 188;} + else if ( (LA17_157==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 189;} + else if ( (LA17_157==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 190;} + else if ( (LA17_157==STAR) && (synpred5_FTS())) {s = 191;} + else if ( (LA17_157==QUESTION_MARK) && (synpred5_FTS())) {s = 192;} + else if ( (LA17_157==DATETIME) && (synpred5_FTS())) {s = 193;} + else if ( (LA17_157==URI) && (synpred5_FTS())) {s = 194;} + else if ( (LA17_157==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_157==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_157==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_157==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_157==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_157==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_157==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_157==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_157==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_157==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_157==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_157==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_157==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_157==COMMA||LA17_157==DOT) && (synpred5_FTS())) {s = 69;} + else if ( (LA17_157==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_157==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_157==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_157==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_157==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_157); + if ( s>=0 ) return s; + break; + + case 41 : + int LA17_118 = input.LA(1); + + int index17_118 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_118==LPAREN) && (synpred4_FTS())) {s = 100;} + else if ( (LA17_118==ID) ) {s = 167;} + else if ( (LA17_118==FTSWORD) ) {s = 106;} + else if ( (LA17_118==FTSPRE) ) {s = 107;} + else if ( (LA17_118==FTSWILD) ) {s = 108;} + else if ( (LA17_118==FTSPHRASE) ) {s = 109;} + else if ( (LA17_118==DECIMAL_INTEGER_LITERAL) ) {s = 110;} + else if ( (LA17_118==FLOATING_POINT_LITERAL) ) {s = 111;} + else if ( (LA17_118==DATETIME) ) {s = 112;} + else if ( (LA17_118==STAR) ) {s = 113;} + else if ( (LA17_118==URI) ) {s = 114;} + else if ( (LA17_118==LSQUARE) && (synpred3_FTS())) {s = 16;} + else if ( (LA17_118==LT) && (synpred3_FTS())) {s = 17;} + else if ( (LA17_118==COMMA||LA17_118==DOT) && (synpred5_FTS())) {s = 115;} + else if ( (LA17_118==NOT) && (synpred5_FTS())) {s = 168;} + else if ( (LA17_118==TO) && (synpred5_FTS())) {s = 169;} + else if ( (LA17_118==QUESTION_MARK) && (synpred5_FTS())) {s = 116;} + + input.seek(index17_118); + if ( s>=0 ) return s; + break; + + case 42 : + int LA17_8 = input.LA(1); + + int index17_8 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_8==STAR) ) {s = 25;} + else if ( (LA17_8==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_8==COMMA||LA17_8==DOT) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_8==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_8==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_8==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_8==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_8==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_8==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_8==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_8==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_8==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_8==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_8==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_8==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_8==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_8==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_8==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_8==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_8==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_8==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_8==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_8==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_8==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_8==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_8==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_8==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_8==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_8==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_8==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_8==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_8==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_8); + if ( s>=0 ) return s; + break; + + case 43 : + int LA17_101 = input.LA(1); + + int index17_101 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_101==DOT) ) {s = 157;} + else if ( (LA17_101==COLON) ) {s = 118;} + else if ( (LA17_101==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_101==COMMA) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_101==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_101==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_101==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_101==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_101==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_101==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_101==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_101==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_101==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_101==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_101==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_101==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_101==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_101==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_101==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_101==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_101==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_101==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_101==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_101==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_101==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_101==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_101==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_101==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_101==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_101==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_101==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_101==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_101==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_101==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_101); + if ( s>=0 ) return s; + break; + + case 44 : + int LA17_6 = input.LA(1); + + int index17_6 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_6==STAR) ) {s = 25;} + else if ( (LA17_6==COLON) ) {s = 26;} + else if ( (LA17_6==COMMA||LA17_6==DOT) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_6==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_6==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_6==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_6==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_6==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_6==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_6==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_6==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_6==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_6==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_6==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_6==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_6==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_6==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_6==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_6==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_6==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_6==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_6==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_6==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_6==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_6==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_6==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_6==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_6==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_6==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_6==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_6==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_6==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_6); + if ( s>=0 ) return s; + break; + + case 45 : + int LA17_15 = input.LA(1); + + int index17_15 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_15==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_15==TILDA) && (synpred5_FTS())) {s = 67;} + else if ( (LA17_15==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_15==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_15==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_15==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_15==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_15==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_15==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_15==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_15==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_15==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_15==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_15==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_15==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_15==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_15==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_15==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_15==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_15==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_15==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_15==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_15==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_15==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_15==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_15==COMMA||LA17_15==DOT) && (synpred5_FTS())) {s = 69;} + else if ( (LA17_15==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_15==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_15==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_15==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_15==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_15==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_15); + if ( s>=0 ) return s; + break; + + case 46 : + int LA17_7 = input.LA(1); + + int index17_7 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_7==STAR) ) {s = 25;} + else if ( (LA17_7==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_7==COMMA||LA17_7==DOT) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_7==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_7==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_7==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_7==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_7==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_7==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_7==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_7==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_7==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_7==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_7==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_7==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_7==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_7==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_7==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_7==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_7==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_7==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_7==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_7==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_7==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_7==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_7==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_7==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_7==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_7==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_7==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_7==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_7==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_7); + if ( s>=0 ) return s; + break; + + case 47 : + int LA17_152 = input.LA(1); + + int index17_152 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 182;} + + input.seek(index17_152); + if ( s>=0 ) return s; + break; + + case 48 : + int LA17_10 = input.LA(1); + + int index17_10 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_10==STAR) ) {s = 25;} + else if ( (LA17_10==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_10==COMMA||LA17_10==DOT) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_10==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_10==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_10==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_10==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_10==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_10==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_10==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_10==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_10==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_10==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_10==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_10==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_10==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_10==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_10==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_10==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_10==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_10==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_10==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_10==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_10==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_10==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_10==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_10==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_10==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_10==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_10==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_10==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_10==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_10); + if ( s>=0 ) return s; + break; + + case 49 : + int LA17_89 = input.LA(1); + + int index17_89 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 151;} + + input.seek(index17_89); + if ( s>=0 ) return s; + break; + + case 50 : + int LA17_5 = input.LA(1); + + int index17_5 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_5==STAR) ) {s = 25;} + else if ( (LA17_5==COLON) ) {s = 26;} + else if ( (LA17_5==COMMA||LA17_5==DOT) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_5==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_5==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_5==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_5==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_5==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_5==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_5==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_5==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_5==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_5==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_5==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_5==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_5==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_5==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_5==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_5==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_5==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_5==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_5==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_5==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_5==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_5==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_5==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_5==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_5==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_5==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_5==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_5==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_5==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_5); + if ( s>=0 ) return s; + break; + + case 51 : + int LA17_102 = input.LA(1); + + int index17_102 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_102==COLON) ) {s = 118;} + else if ( (LA17_102==COMMA||LA17_102==DOT) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_102==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_102==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_102==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_102==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_102==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_102==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_102==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_102==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_102==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_102==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_102==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_102==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_102==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_102==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_102==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_102==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_102==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_102==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_102==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_102==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_102==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_102==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_102==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_102==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_102==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_102==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_102==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_102==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_102==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_102==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_102); + if ( s>=0 ) return s; + break; + + case 52 : + int LA17_105 = input.LA(1); + + int index17_105 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_105==COLON) ) {s = 118;} + else if ( (LA17_105==COMMA||LA17_105==DOT) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_105==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_105==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_105==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_105==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_105==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_105==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_105==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_105==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_105==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_105==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_105==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_105==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_105==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_105==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_105==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_105==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_105==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_105==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_105==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_105==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_105==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_105==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_105==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_105==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_105==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_105==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_105==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_105==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_105==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_105==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_105); + if ( s>=0 ) return s; + break; + + case 53 : + int LA17_88 = input.LA(1); + + int index17_88 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 151;} + + input.seek(index17_88); + if ( s>=0 ) return s; + break; + + case 54 : + int LA17_9 = input.LA(1); + + int index17_9 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_9==STAR) ) {s = 25;} + else if ( (LA17_9==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_9==COMMA||LA17_9==DOT) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_9==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_9==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_9==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_9==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_9==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_9==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_9==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_9==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_9==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_9==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_9==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_9==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_9==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_9==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_9==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_9==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_9==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_9==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_9==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_9==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_9==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_9==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_9==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_9==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_9==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_9==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_9==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_9==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_9==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_9); + if ( s>=0 ) return s; + break; + + case 55 : + int LA17_162 = input.LA(1); + + int index17_162 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_162==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_162==COMMA||LA17_162==DOT) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_162==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_162==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_162==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_162==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_162==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_162==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_162==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_162==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_162==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_162==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_162==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_162==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_162==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_162==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_162==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_162==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_162==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_162==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_162==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_162==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_162==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_162==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_162==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_162==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_162==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_162==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_162==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_162==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_162==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_162==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_162); + if ( s>=0 ) return s; + break; + + case 56 : + int LA17_161 = input.LA(1); + + int index17_161 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_161==DOT) ) {s = 195;} + else if ( (LA17_161==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_161==COMMA) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_161==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_161==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_161==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_161==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_161==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_161==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_161==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_161==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_161==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_161==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_161==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_161==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_161==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_161==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_161==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_161==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_161==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_161==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_161==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_161==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_161==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_161==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_161==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_161==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_161==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_161==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_161==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_161==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_161==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_161==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_161); + if ( s>=0 ) return s; + break; + + case 57 : + int LA17_26 = input.LA(1); + + int index17_26 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_26==LPAREN) && (synpred4_FTS())) {s = 100;} + else if ( (LA17_26==ID) ) {s = 101;} + else if ( (LA17_26==TO) ) {s = 102;} + else if ( (LA17_26==OR) ) {s = 103;} + else if ( (LA17_26==AND) ) {s = 104;} + else if ( (LA17_26==NOT) ) {s = 105;} + else if ( (LA17_26==FTSWORD) ) {s = 106;} + else if ( (LA17_26==FTSPRE) ) {s = 107;} + else if ( (LA17_26==FTSWILD) ) {s = 108;} + else if ( (LA17_26==FTSPHRASE) ) {s = 109;} + else if ( (LA17_26==DECIMAL_INTEGER_LITERAL) ) {s = 110;} + else if ( (LA17_26==FLOATING_POINT_LITERAL) ) {s = 111;} + else if ( (LA17_26==DATETIME) ) {s = 112;} + else if ( (LA17_26==STAR) ) {s = 113;} + else if ( (LA17_26==URI) ) {s = 114;} + else if ( (LA17_26==LSQUARE) && (synpred3_FTS())) {s = 16;} + else if ( (LA17_26==LT) && (synpred3_FTS())) {s = 17;} + else if ( (LA17_26==COMMA||LA17_26==DOT) && (synpred5_FTS())) {s = 115;} + else if ( (LA17_26==QUESTION_MARK) && (synpred5_FTS())) {s = 116;} + + input.seek(index17_26); + if ( s>=0 ) return s; + break; + + case 58 : + int LA17_197 = input.LA(1); + + int index17_197 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 198;} + + input.seek(index17_197); + if ( s>=0 ) return s; + break; + + case 59 : + int LA17_90 = input.LA(1); + + int index17_90 = input.index(); + input.rewind(); + s = -1; + if ( (synpred2_FTS()) ) {s = 124;} + else if ( (synpred5_FTS()) ) {s = 151;} + + input.seek(index17_90); + if ( s>=0 ) return s; + break; + + case 60 : + int LA17_163 = input.LA(1); + + int index17_163 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_163==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_163==COMMA||LA17_163==DOT) && (synpred5_FTS())) {s = 158;} + else if ( (LA17_163==TILDA) && (synpred5_FTS())) {s = 159;} + else if ( (LA17_163==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_163==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_163==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_163==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_163==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_163==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_163==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_163==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_163==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_163==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_163==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_163==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_163==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_163==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_163==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_163==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_163==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_163==STAR) && (synpred5_FTS())) {s = 68;} + else if ( (LA17_163==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_163==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_163==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_163==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_163==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_163==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_163==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_163==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_163==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_163==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_163==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_163); + if ( s>=0 ) return s; + break; + + case 61 : + int LA17_0 = input.LA(1); + + int index17_0 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_0==ID) ) {s = 1;} + else if ( (LA17_0==FTSWORD) ) {s = 2;} + else if ( (LA17_0==FTSPRE) ) {s = 3;} + else if ( (LA17_0==FTSWILD) ) {s = 4;} + else if ( (LA17_0==NOT) ) {s = 5;} + else if ( (LA17_0==TO) ) {s = 6;} + else if ( (LA17_0==DECIMAL_INTEGER_LITERAL) ) {s = 7;} + else if ( (LA17_0==FLOATING_POINT_LITERAL) ) {s = 8;} + else if ( (LA17_0==DATETIME) ) {s = 9;} + else if ( (LA17_0==STAR) ) {s = 10;} + else if ( (LA17_0==URI) ) {s = 11;} + else if ( (LA17_0==AT) ) {s = 12;} + else if ( (LA17_0==OR) ) {s = 13;} + else if ( (LA17_0==AND) ) {s = 14;} + else if ( (LA17_0==FTSPHRASE) ) {s = 15;} + else if ( (LA17_0==LSQUARE) && (synpred3_FTS())) {s = 16;} + else if ( (LA17_0==LT) && (synpred3_FTS())) {s = 17;} + else if ( (LA17_0==COMMA||LA17_0==DOT) && (synpred5_FTS())) {s = 18;} + else if ( (LA17_0==QUESTION_MARK) && (synpred5_FTS())) {s = 19;} + else if ( (LA17_0==EQUALS) && (synpred6_FTS())) {s = 20;} + else if ( (LA17_0==TILDA) && (synpred7_FTS())) {s = 21;} + else if ( (LA17_0==LPAREN) ) {s = 22;} + else if ( (LA17_0==PERCENT) ) {s = 23;} + + input.seek(index17_0); + if ( s>=0 ) return s; + break; + + case 62 : + int LA17_70 = input.LA(1); + + int index17_70 = input.index(); + input.rewind(); + s = -1; + if ( (synpred3_FTS()) ) {s = 27;} + else if ( (synpred4_FTS()) ) {s = 100;} + else if ( (synpred5_FTS()) ) {s = 116;} + + input.seek(index17_70); + if ( s>=0 ) return s; + break; + + case 63 : + int LA17_1 = input.LA(1); + + int index17_1 = input.index(); + input.rewind(); + s = -1; + if ( (LA17_1==DOT) ) {s = 24;} + else if ( (LA17_1==STAR) ) {s = 25;} + else if ( (LA17_1==COLON) ) {s = 26;} + else if ( (LA17_1==DOTDOT) && (synpred3_FTS())) {s = 27;} + else if ( (LA17_1==COMMA) && (synpred5_FTS())) {s = 28;} + else if ( (LA17_1==TILDA) && (synpred5_FTS())) {s = 29;} + else if ( (LA17_1==CARAT) && (synpred5_FTS())) {s = 30;} + else if ( (LA17_1==AND) && (synpred5_FTS())) {s = 31;} + else if ( (LA17_1==AMP) && (synpred5_FTS())) {s = 32;} + else if ( (LA17_1==EOF) && (synpred5_FTS())) {s = 33;} + else if ( (LA17_1==RPAREN) && (synpred5_FTS())) {s = 34;} + else if ( (LA17_1==OR) && (synpred5_FTS())) {s = 35;} + else if ( (LA17_1==BAR) && (synpred5_FTS())) {s = 36;} + else if ( (LA17_1==NOT) && (synpred5_FTS())) {s = 37;} + else if ( (LA17_1==ID) && (synpred5_FTS())) {s = 38;} + else if ( (LA17_1==FTSWORD) && (synpred5_FTS())) {s = 39;} + else if ( (LA17_1==FTSPRE) && (synpred5_FTS())) {s = 40;} + else if ( (LA17_1==FTSWILD) && (synpred5_FTS())) {s = 41;} + else if ( (LA17_1==EXCLAMATION) && (synpred5_FTS())) {s = 42;} + else if ( (LA17_1==TO) && (synpred5_FTS())) {s = 43;} + else if ( (LA17_1==DECIMAL_INTEGER_LITERAL) && (synpred5_FTS())) {s = 44;} + else if ( (LA17_1==FLOATING_POINT_LITERAL) && (synpred5_FTS())) {s = 45;} + else if ( (LA17_1==DATETIME) && (synpred5_FTS())) {s = 46;} + else if ( (LA17_1==URI) && (synpred5_FTS())) {s = 47;} + else if ( (LA17_1==AT) && (synpred5_FTS())) {s = 48;} + else if ( (LA17_1==FTSPHRASE) && (synpred5_FTS())) {s = 49;} + else if ( (LA17_1==LSQUARE) && (synpred5_FTS())) {s = 50;} + else if ( (LA17_1==LT) && (synpred5_FTS())) {s = 51;} + else if ( (LA17_1==QUESTION_MARK) && (synpred5_FTS())) {s = 52;} + else if ( (LA17_1==EQUALS) && (synpred5_FTS())) {s = 53;} + else if ( (LA17_1==LPAREN) && (synpred5_FTS())) {s = 54;} + else if ( (LA17_1==PERCENT) && (synpred5_FTS())) {s = 55;} + else if ( (LA17_1==PLUS) && (synpred5_FTS())) {s = 56;} + else if ( (LA17_1==MINUS) && (synpred5_FTS())) {s = 57;} + + input.seek(index17_1); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 17, _s, input); + error(nvae); + throw nvae; + } + } + + static final String DFA33_eotS = + "\126\uffff"; + static final String DFA33_eofS = + "\2\uffff\2\11\2\uffff\1\11\3\uffff\1\11\1\uffff\7\11\2\uffff\1\11\100"+ + "\uffff"; + static final String DFA33_minS = + "\1\5\1\uffff\2\4\2\uffff\1\4\1\5\2\uffff\1\4\1\uffff\7\4\1\uffff\1\5\1"+ + "\4\2\0\2\12\2\0\1\15\10\0\2\5\1\13\13\0\1\5\42\0"; + static final String DFA33_maxS = + "\1\150\1\uffff\2\150\2\uffff\1\150\1\146\2\uffff\1\150\1\uffff\7\150\1"+ + "\uffff\2\150\2\0\2\12\2\0\1\150\10\0\1\146\2\150\13\0\1\146\42\0"; + static final String DFA33_acceptS = + "\1\uffff\1\1\2\uffff\2\1\2\uffff\1\2\1\3\1\uffff\1\1\7\uffff\1\1\102\uffff"; + static final String DFA33_specialS = + "\1\55\1\uffff\1\72\1\67\2\uffff\1\65\5\uffff\1\14\1\20\1\54\1\53\1\76"+ + "\5\uffff\1\63\1\16\2\uffff\1\56\1\22\1\uffff\1\37\1\77\1\43\1\3\1\60\1"+ + "\11\1\30\1\31\3\uffff\1\2\1\51\1\32\1\75\1\26\1\7\1\57\1\0\1\74\1\46\1"+ + "\64\1\uffff\1\15\1\1\1\52\1\42\1\73\1\23\1\21\1\40\1\100\1\44\1\10\1\70"+ + "\1\4\1\61\1\12\1\33\1\34\1\24\1\50\1\41\1\101\1\45\1\17\1\71\1\5\1\62"+ + "\1\13\1\35\1\36\1\47\1\27\1\66\1\25\1\6}>"; + static final String[] DFA33_transitionS = { + "\1\5\1\1\4\uffff\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\11\31\uffff"+ + "\1\11\2\uffff\1\10\3\11\11\uffff\1\2\16\uffff\1\6\2\uffff\1\4\6\uffff"+ + "\1\11\7\uffff\1\11\5\uffff\1\3\1\uffff\1\7", + "", + "\4\11\1\uffff\1\11\1\13\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\12"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\4\11\1\uffff\1\11\1\13\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\11"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "", + "", + "\4\11\1\uffff\1\11\1\13\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\11"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\1\17\71\uffff\1\14\16\uffff\1\20\2\uffff\1\16\24\uffff\1\15", + "", + "", + "\4\11\1\uffff\1\11\1\uffff\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1"+ + "\11\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\21"+ + "\3\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "", + "\4\11\1\uffff\1\11\1\23\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\22"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\4\11\1\uffff\1\11\1\23\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\11"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\4\11\1\uffff\1\11\1\23\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\11"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\4\11\1\uffff\1\11\1\23\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\11"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\4\11\1\uffff\1\11\1\23\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\11"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\4\11\1\uffff\1\11\1\24\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\2\11"+ + "\1\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\4\11\1\uffff\1\11\1\uffff\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1"+ + "\11\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\25"+ + "\3\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "", + "\1\31\5\uffff\1\34\1\uffff\1\44\1\uffff\1\40\5\uffff\1\34\31\uffff\1"+ + "\41\2\uffff\1\33\1\36\1\37\1\35\11\uffff\1\26\3\uffff\3\11\10\uffff\1"+ + "\32\2\uffff\1\30\6\uffff\1\43\7\uffff\1\42\5\uffff\1\27\1\uffff\1\45", + "\4\11\1\uffff\1\11\1\46\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\2\11"+ + "\1\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\1\uffff", + "\1\uffff", + "\1\47", + "\1\47", + "\1\uffff", + "\1\uffff", + "\1\62\1\uffff\1\56\37\uffff\1\57\3\uffff\1\52\1\53\1\51\11\uffff\1\50"+ + "\16\uffff\1\54\11\uffff\1\61\7\uffff\1\60\5\uffff\1\55\1\uffff\1\63", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\67\71\uffff\1\64\16\uffff\1\70\2\uffff\1\66\24\uffff\1\65", + "\1\11\5\uffff\1\34\1\uffff\1\104\1\uffff\1\100\5\uffff\1\34\31\uffff"+ + "\1\101\2\uffff\1\71\1\74\1\75\1\73\11\uffff\1\72\3\uffff\3\11\10\uffff"+ + "\1\76\2\uffff\1\11\6\uffff\1\103\7\uffff\1\102\5\uffff\1\77\1\uffff\1"+ + "\45", + "\1\34\1\uffff\1\120\1\uffff\1\114\5\uffff\1\34\31\uffff\1\115\2\uffff"+ + "\1\105\1\110\1\111\1\107\11\uffff\1\106\3\uffff\3\11\10\uffff\1\112\11"+ + "\uffff\1\117\7\uffff\1\116\5\uffff\1\113\1\uffff\1\45", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\124\71\uffff\1\121\16\uffff\1\125\2\uffff\1\123\24\uffff\1\122", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff" + }; + + static final short[] DFA33_eot = DFA.unpackEncodedString(DFA33_eotS); + static final short[] DFA33_eof = DFA.unpackEncodedString(DFA33_eofS); + static final char[] DFA33_min = DFA.unpackEncodedStringToUnsignedChars(DFA33_minS); + static final char[] DFA33_max = DFA.unpackEncodedStringToUnsignedChars(DFA33_maxS); + static final short[] DFA33_accept = DFA.unpackEncodedString(DFA33_acceptS); + static final short[] DFA33_special = DFA.unpackEncodedString(DFA33_specialS); + static final short[][] DFA33_transition; + + static { + int numStates = DFA33_transitionS.length; + DFA33_transition = new short[numStates][]; + for (int i=0; i fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( EXACT_PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( EXACT_TERM ftsWord fieldReference ( fuzzy )? ) ) | FTSPHRASE ( ( slop )=> slop )? -> ^( EXACT_PHRASE FTSPHRASE ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( EXACT_TERM ftsWord ( fuzzy )? ) )"; + } + @Override + public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { + TokenStream input = (TokenStream)_input; + int _s = s; + switch ( s ) { + case 0 : + int LA33_47 = input.LA(1); + + int index33_47 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_47); + if ( s>=0 ) return s; + break; + + case 1 : + int LA33_53 = input.LA(1); + + int index33_53 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_53); + if ( s>=0 ) return s; + break; + + case 2 : + int LA33_40 = input.LA(1); + + int index33_40 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_40); + if ( s>=0 ) return s; + break; + + case 3 : + int LA33_32 = input.LA(1); + + int index33_32 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_32); + if ( s>=0 ) return s; + break; + + case 4 : + int LA33_64 = input.LA(1); + + int index33_64 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_64); + if ( s>=0 ) return s; + break; + + case 5 : + int LA33_76 = input.LA(1); + + int index33_76 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_76); + if ( s>=0 ) return s; + break; + + case 6 : + int LA33_85 = input.LA(1); + + int index33_85 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_85); + if ( s>=0 ) return s; + break; + + case 7 : + int LA33_45 = input.LA(1); + + int index33_45 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_45); + if ( s>=0 ) return s; + break; + + case 8 : + int LA33_62 = input.LA(1); + + int index33_62 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_62); + if ( s>=0 ) return s; + break; + + case 9 : + int LA33_34 = input.LA(1); + + int index33_34 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_34); + if ( s>=0 ) return s; + break; + + case 10 : + int LA33_66 = input.LA(1); + + int index33_66 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_66); + if ( s>=0 ) return s; + break; + + case 11 : + int LA33_78 = input.LA(1); + + int index33_78 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_78); + if ( s>=0 ) return s; + break; + + case 12 : + int LA33_12 = input.LA(1); + + int index33_12 = input.index(); + input.rewind(); + s = -1; + if ( (LA33_12==DOT) ) {s = 18;} + else if ( (LA33_12==COLON) && (synpred13_FTS())) {s = 19;} + else if ( (LA33_12==EOF||(LA33_12 >= AMP && LA33_12 <= BAR)||LA33_12==CARAT||LA33_12==COMMA||LA33_12==DATETIME||LA33_12==DECIMAL_INTEGER_LITERAL||LA33_12==EQUALS||LA33_12==EXCLAMATION||LA33_12==FLOATING_POINT_LITERAL||(LA33_12 >= FTSPHRASE && LA33_12 <= FTSWORD)||LA33_12==ID||(LA33_12 >= LPAREN && LA33_12 <= LT)||LA33_12==MINUS||LA33_12==NOT||(LA33_12 >= OR && LA33_12 <= PERCENT)||LA33_12==PLUS||LA33_12==QUESTION_MARK||LA33_12==RPAREN||LA33_12==STAR||(LA33_12 >= TILDA && LA33_12 <= TO)||LA33_12==URI) ) {s = 9;} + + input.seek(index33_12); + if ( s>=0 ) return s; + break; + + case 13 : + int LA33_52 = input.LA(1); + + int index33_52 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_52); + if ( s>=0 ) return s; + break; + + case 14 : + int LA33_23 = input.LA(1); + + int index33_23 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_23); + if ( s>=0 ) return s; + break; + + case 15 : + int LA33_74 = input.LA(1); + + int index33_74 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_74); + if ( s>=0 ) return s; + break; + + case 16 : + int LA33_13 = input.LA(1); + + int index33_13 = input.index(); + input.rewind(); + s = -1; + if ( (LA33_13==COLON) && (synpred13_FTS())) {s = 19;} + else if ( (LA33_13==EOF||(LA33_13 >= AMP && LA33_13 <= BAR)||LA33_13==CARAT||LA33_13==COMMA||LA33_13==DATETIME||LA33_13==DECIMAL_INTEGER_LITERAL||LA33_13==DOT||LA33_13==EQUALS||LA33_13==EXCLAMATION||LA33_13==FLOATING_POINT_LITERAL||(LA33_13 >= FTSPHRASE && LA33_13 <= FTSWORD)||LA33_13==ID||(LA33_13 >= LPAREN && LA33_13 <= LT)||LA33_13==MINUS||LA33_13==NOT||(LA33_13 >= OR && LA33_13 <= PERCENT)||LA33_13==PLUS||LA33_13==QUESTION_MARK||LA33_13==RPAREN||LA33_13==STAR||(LA33_13 >= TILDA && LA33_13 <= TO)||LA33_13==URI) ) {s = 9;} + + input.seek(index33_13); + if ( s>=0 ) return s; + break; + + case 17 : + int LA33_58 = input.LA(1); + + int index33_58 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_58); + if ( s>=0 ) return s; + break; + + case 18 : + int LA33_27 = input.LA(1); + + int index33_27 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_27); + if ( s>=0 ) return s; + break; + + case 19 : + int LA33_57 = input.LA(1); + + int index33_57 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_57); + if ( s>=0 ) return s; + break; + + case 20 : + int LA33_69 = input.LA(1); + + int index33_69 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_69); + if ( s>=0 ) return s; + break; + + case 21 : + int LA33_84 = input.LA(1); + + int index33_84 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_84); + if ( s>=0 ) return s; + break; + + case 22 : + int LA33_44 = input.LA(1); + + int index33_44 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_44); + if ( s>=0 ) return s; + break; + + case 23 : + int LA33_82 = input.LA(1); + + int index33_82 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_82); + if ( s>=0 ) return s; + break; + + case 24 : + int LA33_35 = input.LA(1); + + int index33_35 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_35); + if ( s>=0 ) return s; + break; + + case 25 : + int LA33_36 = input.LA(1); + + int index33_36 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_36); + if ( s>=0 ) return s; + break; + + case 26 : + int LA33_42 = input.LA(1); + + int index33_42 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_42); + if ( s>=0 ) return s; + break; + + case 27 : + int LA33_67 = input.LA(1); + + int index33_67 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_67); + if ( s>=0 ) return s; + break; + + case 28 : + int LA33_68 = input.LA(1); + + int index33_68 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_68); + if ( s>=0 ) return s; + break; + + case 29 : + int LA33_79 = input.LA(1); + + int index33_79 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_79); + if ( s>=0 ) return s; + break; + + case 30 : + int LA33_80 = input.LA(1); + + int index33_80 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_80); + if ( s>=0 ) return s; + break; + + case 31 : + int LA33_29 = input.LA(1); + + int index33_29 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_29); + if ( s>=0 ) return s; + break; + + case 32 : + int LA33_59 = input.LA(1); + + int index33_59 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_59); + if ( s>=0 ) return s; + break; + + case 33 : + int LA33_71 = input.LA(1); + + int index33_71 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_71); + if ( s>=0 ) return s; + break; + + case 34 : + int LA33_55 = input.LA(1); + + int index33_55 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_55); + if ( s>=0 ) return s; + break; + + case 35 : + int LA33_31 = input.LA(1); + + int index33_31 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_31); + if ( s>=0 ) return s; + break; + + case 36 : + int LA33_61 = input.LA(1); + + int index33_61 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_61); + if ( s>=0 ) return s; + break; + + case 37 : + int LA33_73 = input.LA(1); + + int index33_73 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_73); + if ( s>=0 ) return s; + break; + + case 38 : + int LA33_49 = input.LA(1); + + int index33_49 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_49); + if ( s>=0 ) return s; + break; + + case 39 : + int LA33_81 = input.LA(1); + + int index33_81 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_81); + if ( s>=0 ) return s; + break; + + case 40 : + int LA33_70 = input.LA(1); + + int index33_70 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_70); + if ( s>=0 ) return s; + break; + + case 41 : + int LA33_41 = input.LA(1); + + int index33_41 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_41); + if ( s>=0 ) return s; + break; + + case 42 : + int LA33_54 = input.LA(1); + + int index33_54 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_54); + if ( s>=0 ) return s; + break; + + case 43 : + int LA33_15 = input.LA(1); + + int index33_15 = input.index(); + input.rewind(); + s = -1; + if ( (LA33_15==COLON) && (synpred13_FTS())) {s = 19;} + else if ( (LA33_15==EOF||(LA33_15 >= AMP && LA33_15 <= BAR)||LA33_15==CARAT||LA33_15==COMMA||LA33_15==DATETIME||LA33_15==DECIMAL_INTEGER_LITERAL||LA33_15==DOT||LA33_15==EQUALS||LA33_15==EXCLAMATION||LA33_15==FLOATING_POINT_LITERAL||(LA33_15 >= FTSPHRASE && LA33_15 <= FTSWORD)||LA33_15==ID||(LA33_15 >= LPAREN && LA33_15 <= LT)||LA33_15==MINUS||LA33_15==NOT||(LA33_15 >= OR && LA33_15 <= PERCENT)||LA33_15==PLUS||LA33_15==QUESTION_MARK||LA33_15==RPAREN||LA33_15==STAR||(LA33_15 >= TILDA && LA33_15 <= TO)||LA33_15==URI) ) {s = 9;} + + input.seek(index33_15); + if ( s>=0 ) return s; + break; + + case 44 : + int LA33_14 = input.LA(1); + + int index33_14 = input.index(); + input.rewind(); + s = -1; + if ( (LA33_14==COLON) && (synpred13_FTS())) {s = 19;} + else if ( (LA33_14==EOF||(LA33_14 >= AMP && LA33_14 <= BAR)||LA33_14==CARAT||LA33_14==COMMA||LA33_14==DATETIME||LA33_14==DECIMAL_INTEGER_LITERAL||LA33_14==DOT||LA33_14==EQUALS||LA33_14==EXCLAMATION||LA33_14==FLOATING_POINT_LITERAL||(LA33_14 >= FTSPHRASE && LA33_14 <= FTSWORD)||LA33_14==ID||(LA33_14 >= LPAREN && LA33_14 <= LT)||LA33_14==MINUS||LA33_14==NOT||(LA33_14 >= OR && LA33_14 <= PERCENT)||LA33_14==PLUS||LA33_14==QUESTION_MARK||LA33_14==RPAREN||LA33_14==STAR||(LA33_14 >= TILDA && LA33_14 <= TO)||LA33_14==URI) ) {s = 9;} + + input.seek(index33_14); + if ( s>=0 ) return s; + break; + + case 45 : + int LA33_0 = input.LA(1); + + int index33_0 = input.index(); + input.rewind(); + s = -1; + if ( (LA33_0==AT) && (synpred13_FTS())) {s = 1;} + else if ( (LA33_0==ID) ) {s = 2;} + else if ( (LA33_0==TO) ) {s = 3;} + else if ( (LA33_0==OR) && (synpred13_FTS())) {s = 4;} + else if ( (LA33_0==AND) && (synpred13_FTS())) {s = 5;} + else if ( (LA33_0==NOT) ) {s = 6;} + else if ( (LA33_0==URI) ) {s = 7;} + else if ( (LA33_0==FTSPHRASE) ) {s = 8;} + else if ( (LA33_0==COMMA||LA33_0==DATETIME||LA33_0==DECIMAL_INTEGER_LITERAL||LA33_0==DOT||LA33_0==FLOATING_POINT_LITERAL||(LA33_0 >= FTSPRE && LA33_0 <= FTSWORD)||LA33_0==QUESTION_MARK||LA33_0==STAR) ) {s = 9;} + + input.seek(index33_0); + if ( s>=0 ) return s; + break; + + case 46 : + int LA33_26 = input.LA(1); + + int index33_26 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_26); + if ( s>=0 ) return s; + break; + + case 47 : + int LA33_46 = input.LA(1); + + int index33_46 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_46); + if ( s>=0 ) return s; + break; + + case 48 : + int LA33_33 = input.LA(1); + + int index33_33 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_33); + if ( s>=0 ) return s; + break; + + case 49 : + int LA33_65 = input.LA(1); + + int index33_65 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_65); + if ( s>=0 ) return s; + break; + + case 50 : + int LA33_77 = input.LA(1); + + int index33_77 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_77); + if ( s>=0 ) return s; + break; + + case 51 : + int LA33_22 = input.LA(1); + + int index33_22 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_22); + if ( s>=0 ) return s; + break; + + case 52 : + int LA33_50 = input.LA(1); + + int index33_50 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_50); + if ( s>=0 ) return s; + break; + + case 53 : + int LA33_6 = input.LA(1); + + int index33_6 = input.index(); + input.rewind(); + s = -1; + if ( (LA33_6==COLON) && (synpred13_FTS())) {s = 11;} + else if ( (LA33_6==EOF||(LA33_6 >= AMP && LA33_6 <= BAR)||LA33_6==CARAT||LA33_6==COMMA||LA33_6==DATETIME||LA33_6==DECIMAL_INTEGER_LITERAL||LA33_6==DOT||LA33_6==EQUALS||LA33_6==EXCLAMATION||LA33_6==FLOATING_POINT_LITERAL||(LA33_6 >= FTSPHRASE && LA33_6 <= FTSWORD)||LA33_6==ID||(LA33_6 >= LPAREN && LA33_6 <= LT)||LA33_6==MINUS||LA33_6==NOT||(LA33_6 >= OR && LA33_6 <= PERCENT)||LA33_6==PLUS||LA33_6==QUESTION_MARK||LA33_6==RPAREN||LA33_6==STAR||(LA33_6 >= TILDA && LA33_6 <= TO)||LA33_6==URI) ) {s = 9;} + + input.seek(index33_6); + if ( s>=0 ) return s; + break; + + case 54 : + int LA33_83 = input.LA(1); + + int index33_83 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_83); + if ( s>=0 ) return s; + break; + + case 55 : + int LA33_3 = input.LA(1); + + int index33_3 = input.index(); + input.rewind(); + s = -1; + if ( (LA33_3==COLON) && (synpred13_FTS())) {s = 11;} + else if ( (LA33_3==EOF||(LA33_3 >= AMP && LA33_3 <= BAR)||LA33_3==CARAT||LA33_3==COMMA||LA33_3==DATETIME||LA33_3==DECIMAL_INTEGER_LITERAL||LA33_3==DOT||LA33_3==EQUALS||LA33_3==EXCLAMATION||LA33_3==FLOATING_POINT_LITERAL||(LA33_3 >= FTSPHRASE && LA33_3 <= FTSWORD)||LA33_3==ID||(LA33_3 >= LPAREN && LA33_3 <= LT)||LA33_3==MINUS||LA33_3==NOT||(LA33_3 >= OR && LA33_3 <= PERCENT)||LA33_3==PLUS||LA33_3==QUESTION_MARK||LA33_3==RPAREN||LA33_3==STAR||(LA33_3 >= TILDA && LA33_3 <= TO)||LA33_3==URI) ) {s = 9;} + + input.seek(index33_3); + if ( s>=0 ) return s; + break; + + case 56 : + int LA33_63 = input.LA(1); + + int index33_63 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_63); + if ( s>=0 ) return s; + break; + + case 57 : + int LA33_75 = input.LA(1); + + int index33_75 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_75); + if ( s>=0 ) return s; + break; + + case 58 : + int LA33_2 = input.LA(1); + + int index33_2 = input.index(); + input.rewind(); + s = -1; + if ( (LA33_2==DOT) ) {s = 10;} + else if ( (LA33_2==COLON) && (synpred13_FTS())) {s = 11;} + else if ( (LA33_2==EOF||(LA33_2 >= AMP && LA33_2 <= BAR)||LA33_2==CARAT||LA33_2==COMMA||LA33_2==DATETIME||LA33_2==DECIMAL_INTEGER_LITERAL||LA33_2==EQUALS||LA33_2==EXCLAMATION||LA33_2==FLOATING_POINT_LITERAL||(LA33_2 >= FTSPHRASE && LA33_2 <= FTSWORD)||LA33_2==ID||(LA33_2 >= LPAREN && LA33_2 <= LT)||LA33_2==MINUS||LA33_2==NOT||(LA33_2 >= OR && LA33_2 <= PERCENT)||LA33_2==PLUS||LA33_2==QUESTION_MARK||LA33_2==RPAREN||LA33_2==STAR||(LA33_2 >= TILDA && LA33_2 <= TO)||LA33_2==URI) ) {s = 9;} + + input.seek(index33_2); + if ( s>=0 ) return s; + break; + + case 59 : + int LA33_56 = input.LA(1); + + int index33_56 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_56); + if ( s>=0 ) return s; + break; + + case 60 : + int LA33_48 = input.LA(1); + + int index33_48 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_48); + if ( s>=0 ) return s; + break; + + case 61 : + int LA33_43 = input.LA(1); + + int index33_43 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_43); + if ( s>=0 ) return s; + break; + + case 62 : + int LA33_16 = input.LA(1); + + int index33_16 = input.index(); + input.rewind(); + s = -1; + if ( (LA33_16==COLON) && (synpred13_FTS())) {s = 19;} + else if ( (LA33_16==EOF||(LA33_16 >= AMP && LA33_16 <= BAR)||LA33_16==CARAT||LA33_16==COMMA||LA33_16==DATETIME||LA33_16==DECIMAL_INTEGER_LITERAL||LA33_16==DOT||LA33_16==EQUALS||LA33_16==EXCLAMATION||LA33_16==FLOATING_POINT_LITERAL||(LA33_16 >= FTSPHRASE && LA33_16 <= FTSWORD)||LA33_16==ID||(LA33_16 >= LPAREN && LA33_16 <= LT)||LA33_16==MINUS||LA33_16==NOT||(LA33_16 >= OR && LA33_16 <= PERCENT)||LA33_16==PLUS||LA33_16==QUESTION_MARK||LA33_16==RPAREN||LA33_16==STAR||(LA33_16 >= TILDA && LA33_16 <= TO)||LA33_16==URI) ) {s = 9;} + + input.seek(index33_16); + if ( s>=0 ) return s; + break; + + case 63 : + int LA33_30 = input.LA(1); + + int index33_30 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_30); + if ( s>=0 ) return s; + break; + + case 64 : + int LA33_60 = input.LA(1); + + int index33_60 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_60); + if ( s>=0 ) return s; + break; + + case 65 : + int LA33_72 = input.LA(1); + + int index33_72 = input.index(); + input.rewind(); + s = -1; + if ( (synpred13_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index33_72); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 33, _s, input); + error(nvae); + throw nvae; + } + } + + static final String DFA39_eotS = + "\126\uffff"; + static final String DFA39_eofS = + "\2\uffff\2\11\2\uffff\1\11\3\uffff\1\11\1\uffff\7\11\2\uffff\1\11\100"+ + "\uffff"; + static final String DFA39_minS = + "\1\5\1\uffff\2\4\2\uffff\1\4\1\5\2\uffff\1\4\1\uffff\7\4\1\uffff\1\5\1"+ + "\4\2\0\2\12\2\0\1\15\10\0\2\5\1\13\13\0\1\5\42\0"; + static final String DFA39_maxS = + "\1\150\1\uffff\2\150\2\uffff\1\150\1\146\2\uffff\1\150\1\uffff\7\150\1"+ + "\uffff\2\150\2\0\2\12\2\0\1\150\10\0\1\146\2\150\13\0\1\146\42\0"; + static final String DFA39_acceptS = + "\1\uffff\1\1\2\uffff\2\1\2\uffff\1\2\1\3\1\uffff\1\1\7\uffff\1\1\102\uffff"; + static final String DFA39_specialS = + "\1\51\1\uffff\1\101\1\74\2\uffff\1\52\5\uffff\1\67\1\11\1\42\1\57\1\45"+ + "\5\uffff\1\35\1\2\2\uffff\1\3\1\60\1\uffff\1\30\1\13\1\53\1\4\1\76\1\36"+ + "\1\21\1\22\3\uffff\1\44\1\70\1\23\1\12\1\50\1\10\1\75\1\41\1\73\1\56\1"+ + "\16\1\uffff\1\64\1\43\1\71\1\33\1\72\1\61\1\46\1\31\1\14\1\54\1\34\1\0"+ + "\1\5\1\77\1\37\1\24\1\25\1\62\1\66\1\32\1\15\1\55\1\65\1\1\1\6\1\100\1"+ + "\40\1\26\1\27\1\63\1\20\1\17\1\47\1\7}>"; + static final String[] DFA39_transitionS = { + "\1\5\1\1\4\uffff\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\11\31\uffff"+ + "\1\11\2\uffff\1\10\3\11\11\uffff\1\2\16\uffff\1\6\2\uffff\1\4\6\uffff"+ + "\1\11\7\uffff\1\11\5\uffff\1\3\1\uffff\1\7", + "", + "\4\11\1\uffff\1\11\1\13\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\12"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\4\11\1\uffff\1\11\1\13\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\11"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "", + "", + "\4\11\1\uffff\1\11\1\13\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\11"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\1\17\71\uffff\1\14\16\uffff\1\20\2\uffff\1\16\24\uffff\1\15", + "", + "", + "\4\11\1\uffff\1\11\1\uffff\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1"+ + "\11\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\21"+ + "\3\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "", + "\4\11\1\uffff\1\11\1\23\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\22"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\4\11\1\uffff\1\11\1\23\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\11"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\4\11\1\uffff\1\11\1\23\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\11"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\4\11\1\uffff\1\11\1\23\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\11"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\4\11\1\uffff\1\11\1\23\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1\11"+ + "\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\4\11\1\uffff\1\11\1\24\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\2\11"+ + "\1\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\4\11\1\uffff\1\11\1\uffff\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\1"+ + "\11\2\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\25"+ + "\3\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "", + "\1\31\5\uffff\1\34\1\uffff\1\44\1\uffff\1\40\5\uffff\1\34\31\uffff\1"+ + "\41\2\uffff\1\33\1\36\1\37\1\35\11\uffff\1\26\3\uffff\3\11\10\uffff\1"+ + "\32\2\uffff\1\30\6\uffff\1\43\7\uffff\1\42\5\uffff\1\27\1\uffff\1\45", + "\4\11\1\uffff\1\11\1\46\1\11\1\uffff\1\11\1\uffff\1\11\5\uffff\2\11"+ + "\1\uffff\1\11\2\uffff\1\11\23\uffff\1\11\2\uffff\4\11\11\uffff\1\11\3"+ + "\uffff\3\11\2\uffff\1\11\5\uffff\1\11\2\uffff\2\11\1\uffff\1\11\3\uffff"+ + "\1\11\2\uffff\1\11\4\uffff\1\11\4\uffff\2\11\1\uffff\1\11", + "\1\uffff", + "\1\uffff", + "\1\47", + "\1\47", + "\1\uffff", + "\1\uffff", + "\1\62\1\uffff\1\56\37\uffff\1\57\3\uffff\1\52\1\53\1\51\11\uffff\1\50"+ + "\16\uffff\1\54\11\uffff\1\61\7\uffff\1\60\5\uffff\1\55\1\uffff\1\63", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\67\71\uffff\1\64\16\uffff\1\70\2\uffff\1\66\24\uffff\1\65", + "\1\11\5\uffff\1\34\1\uffff\1\104\1\uffff\1\100\5\uffff\1\34\31\uffff"+ + "\1\101\2\uffff\1\71\1\74\1\75\1\73\11\uffff\1\72\3\uffff\3\11\10\uffff"+ + "\1\76\2\uffff\1\11\6\uffff\1\103\7\uffff\1\102\5\uffff\1\77\1\uffff\1"+ + "\45", + "\1\34\1\uffff\1\120\1\uffff\1\114\5\uffff\1\34\31\uffff\1\115\2\uffff"+ + "\1\105\1\110\1\111\1\107\11\uffff\1\106\3\uffff\3\11\10\uffff\1\112\11"+ + "\uffff\1\117\7\uffff\1\116\5\uffff\1\113\1\uffff\1\45", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\124\71\uffff\1\121\16\uffff\1\125\2\uffff\1\123\24\uffff\1\122", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff" + }; + + static final short[] DFA39_eot = DFA.unpackEncodedString(DFA39_eotS); + static final short[] DFA39_eof = DFA.unpackEncodedString(DFA39_eofS); + static final char[] DFA39_min = DFA.unpackEncodedStringToUnsignedChars(DFA39_minS); + static final char[] DFA39_max = DFA.unpackEncodedStringToUnsignedChars(DFA39_maxS); + static final short[] DFA39_accept = DFA.unpackEncodedString(DFA39_acceptS); + static final short[] DFA39_special = DFA.unpackEncodedString(DFA39_specialS); + static final short[][] DFA39_transition; + + static { + int numStates = DFA39_transitionS.length; + DFA39_transition = new short[numStates][]; + for (int i=0; i fieldReference COLON ( FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE fieldReference ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord fieldReference ( fuzzy )? ) ) | FTSPHRASE ( ( slop )=> slop )? -> ^( PHRASE FTSPHRASE ( slop )? ) | ftsWord ( ( fuzzy )=> fuzzy )? -> ^( TERM ftsWord ( fuzzy )? ) )"; + } + @Override + public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { + TokenStream input = (TokenStream)_input; + int _s = s; + switch ( s ) { + case 0 : + int LA39_63 = input.LA(1); + + int index39_63 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_63); + if ( s>=0 ) return s; + break; + + case 1 : + int LA39_75 = input.LA(1); + + int index39_75 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_75); + if ( s>=0 ) return s; + break; + + case 2 : + int LA39_23 = input.LA(1); + + int index39_23 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_23); + if ( s>=0 ) return s; + break; + + case 3 : + int LA39_26 = input.LA(1); + + int index39_26 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_26); + if ( s>=0 ) return s; + break; + + case 4 : + int LA39_32 = input.LA(1); + + int index39_32 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_32); + if ( s>=0 ) return s; + break; + + case 5 : + int LA39_64 = input.LA(1); + + int index39_64 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_64); + if ( s>=0 ) return s; + break; + + case 6 : + int LA39_76 = input.LA(1); + + int index39_76 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_76); + if ( s>=0 ) return s; + break; + + case 7 : + int LA39_85 = input.LA(1); + + int index39_85 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_85); + if ( s>=0 ) return s; + break; + + case 8 : + int LA39_45 = input.LA(1); + + int index39_45 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_45); + if ( s>=0 ) return s; + break; + + case 9 : + int LA39_13 = input.LA(1); + + int index39_13 = input.index(); + input.rewind(); + s = -1; + if ( (LA39_13==COLON) && (synpred18_FTS())) {s = 19;} + else if ( (LA39_13==EOF||(LA39_13 >= AMP && LA39_13 <= BAR)||LA39_13==CARAT||LA39_13==COMMA||LA39_13==DATETIME||LA39_13==DECIMAL_INTEGER_LITERAL||LA39_13==DOT||LA39_13==EQUALS||LA39_13==EXCLAMATION||LA39_13==FLOATING_POINT_LITERAL||(LA39_13 >= FTSPHRASE && LA39_13 <= FTSWORD)||LA39_13==ID||(LA39_13 >= LPAREN && LA39_13 <= LT)||LA39_13==MINUS||LA39_13==NOT||(LA39_13 >= OR && LA39_13 <= PERCENT)||LA39_13==PLUS||LA39_13==QUESTION_MARK||LA39_13==RPAREN||LA39_13==STAR||(LA39_13 >= TILDA && LA39_13 <= TO)||LA39_13==URI) ) {s = 9;} + + input.seek(index39_13); + if ( s>=0 ) return s; + break; + + case 10 : + int LA39_43 = input.LA(1); + + int index39_43 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_43); + if ( s>=0 ) return s; + break; + + case 11 : + int LA39_30 = input.LA(1); + + int index39_30 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_30); + if ( s>=0 ) return s; + break; + + case 12 : + int LA39_60 = input.LA(1); + + int index39_60 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_60); + if ( s>=0 ) return s; + break; + + case 13 : + int LA39_72 = input.LA(1); + + int index39_72 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_72); + if ( s>=0 ) return s; + break; + + case 14 : + int LA39_50 = input.LA(1); + + int index39_50 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_50); + if ( s>=0 ) return s; + break; + + case 15 : + int LA39_83 = input.LA(1); + + int index39_83 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_83); + if ( s>=0 ) return s; + break; + + case 16 : + int LA39_82 = input.LA(1); + + int index39_82 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_82); + if ( s>=0 ) return s; + break; + + case 17 : + int LA39_35 = input.LA(1); + + int index39_35 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_35); + if ( s>=0 ) return s; + break; + + case 18 : + int LA39_36 = input.LA(1); + + int index39_36 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_36); + if ( s>=0 ) return s; + break; + + case 19 : + int LA39_42 = input.LA(1); + + int index39_42 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_42); + if ( s>=0 ) return s; + break; + + case 20 : + int LA39_67 = input.LA(1); + + int index39_67 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_67); + if ( s>=0 ) return s; + break; + + case 21 : + int LA39_68 = input.LA(1); + + int index39_68 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_68); + if ( s>=0 ) return s; + break; + + case 22 : + int LA39_79 = input.LA(1); + + int index39_79 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_79); + if ( s>=0 ) return s; + break; + + case 23 : + int LA39_80 = input.LA(1); + + int index39_80 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_80); + if ( s>=0 ) return s; + break; + + case 24 : + int LA39_29 = input.LA(1); + + int index39_29 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_29); + if ( s>=0 ) return s; + break; + + case 25 : + int LA39_59 = input.LA(1); + + int index39_59 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_59); + if ( s>=0 ) return s; + break; + + case 26 : + int LA39_71 = input.LA(1); + + int index39_71 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_71); + if ( s>=0 ) return s; + break; + + case 27 : + int LA39_55 = input.LA(1); + + int index39_55 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_55); + if ( s>=0 ) return s; + break; + + case 28 : + int LA39_62 = input.LA(1); + + int index39_62 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_62); + if ( s>=0 ) return s; + break; + + case 29 : + int LA39_22 = input.LA(1); + + int index39_22 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_22); + if ( s>=0 ) return s; + break; + + case 30 : + int LA39_34 = input.LA(1); + + int index39_34 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_34); + if ( s>=0 ) return s; + break; + + case 31 : + int LA39_66 = input.LA(1); + + int index39_66 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_66); + if ( s>=0 ) return s; + break; + + case 32 : + int LA39_78 = input.LA(1); + + int index39_78 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_78); + if ( s>=0 ) return s; + break; + + case 33 : + int LA39_47 = input.LA(1); + + int index39_47 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_47); + if ( s>=0 ) return s; + break; + + case 34 : + int LA39_14 = input.LA(1); + + int index39_14 = input.index(); + input.rewind(); + s = -1; + if ( (LA39_14==COLON) && (synpred18_FTS())) {s = 19;} + else if ( (LA39_14==EOF||(LA39_14 >= AMP && LA39_14 <= BAR)||LA39_14==CARAT||LA39_14==COMMA||LA39_14==DATETIME||LA39_14==DECIMAL_INTEGER_LITERAL||LA39_14==DOT||LA39_14==EQUALS||LA39_14==EXCLAMATION||LA39_14==FLOATING_POINT_LITERAL||(LA39_14 >= FTSPHRASE && LA39_14 <= FTSWORD)||LA39_14==ID||(LA39_14 >= LPAREN && LA39_14 <= LT)||LA39_14==MINUS||LA39_14==NOT||(LA39_14 >= OR && LA39_14 <= PERCENT)||LA39_14==PLUS||LA39_14==QUESTION_MARK||LA39_14==RPAREN||LA39_14==STAR||(LA39_14 >= TILDA && LA39_14 <= TO)||LA39_14==URI) ) {s = 9;} + + input.seek(index39_14); + if ( s>=0 ) return s; + break; + + case 35 : + int LA39_53 = input.LA(1); + + int index39_53 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_53); + if ( s>=0 ) return s; + break; + + case 36 : + int LA39_40 = input.LA(1); + + int index39_40 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_40); + if ( s>=0 ) return s; + break; + + case 37 : + int LA39_16 = input.LA(1); + + int index39_16 = input.index(); + input.rewind(); + s = -1; + if ( (LA39_16==COLON) && (synpred18_FTS())) {s = 19;} + else if ( (LA39_16==EOF||(LA39_16 >= AMP && LA39_16 <= BAR)||LA39_16==CARAT||LA39_16==COMMA||LA39_16==DATETIME||LA39_16==DECIMAL_INTEGER_LITERAL||LA39_16==DOT||LA39_16==EQUALS||LA39_16==EXCLAMATION||LA39_16==FLOATING_POINT_LITERAL||(LA39_16 >= FTSPHRASE && LA39_16 <= FTSWORD)||LA39_16==ID||(LA39_16 >= LPAREN && LA39_16 <= LT)||LA39_16==MINUS||LA39_16==NOT||(LA39_16 >= OR && LA39_16 <= PERCENT)||LA39_16==PLUS||LA39_16==QUESTION_MARK||LA39_16==RPAREN||LA39_16==STAR||(LA39_16 >= TILDA && LA39_16 <= TO)||LA39_16==URI) ) {s = 9;} + + input.seek(index39_16); + if ( s>=0 ) return s; + break; + + case 38 : + int LA39_58 = input.LA(1); + + int index39_58 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_58); + if ( s>=0 ) return s; + break; + + case 39 : + int LA39_84 = input.LA(1); + + int index39_84 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_84); + if ( s>=0 ) return s; + break; + + case 40 : + int LA39_44 = input.LA(1); + + int index39_44 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_44); + if ( s>=0 ) return s; + break; + + case 41 : + int LA39_0 = input.LA(1); + + int index39_0 = input.index(); + input.rewind(); + s = -1; + if ( (LA39_0==AT) && (synpred18_FTS())) {s = 1;} + else if ( (LA39_0==ID) ) {s = 2;} + else if ( (LA39_0==TO) ) {s = 3;} + else if ( (LA39_0==OR) && (synpred18_FTS())) {s = 4;} + else if ( (LA39_0==AND) && (synpred18_FTS())) {s = 5;} + else if ( (LA39_0==NOT) ) {s = 6;} + else if ( (LA39_0==URI) ) {s = 7;} + else if ( (LA39_0==FTSPHRASE) ) {s = 8;} + else if ( (LA39_0==COMMA||LA39_0==DATETIME||LA39_0==DECIMAL_INTEGER_LITERAL||LA39_0==DOT||LA39_0==FLOATING_POINT_LITERAL||(LA39_0 >= FTSPRE && LA39_0 <= FTSWORD)||LA39_0==QUESTION_MARK||LA39_0==STAR) ) {s = 9;} + + input.seek(index39_0); + if ( s>=0 ) return s; + break; + + case 42 : + int LA39_6 = input.LA(1); + + int index39_6 = input.index(); + input.rewind(); + s = -1; + if ( (LA39_6==COLON) && (synpred18_FTS())) {s = 11;} + else if ( (LA39_6==EOF||(LA39_6 >= AMP && LA39_6 <= BAR)||LA39_6==CARAT||LA39_6==COMMA||LA39_6==DATETIME||LA39_6==DECIMAL_INTEGER_LITERAL||LA39_6==DOT||LA39_6==EQUALS||LA39_6==EXCLAMATION||LA39_6==FLOATING_POINT_LITERAL||(LA39_6 >= FTSPHRASE && LA39_6 <= FTSWORD)||LA39_6==ID||(LA39_6 >= LPAREN && LA39_6 <= LT)||LA39_6==MINUS||LA39_6==NOT||(LA39_6 >= OR && LA39_6 <= PERCENT)||LA39_6==PLUS||LA39_6==QUESTION_MARK||LA39_6==RPAREN||LA39_6==STAR||(LA39_6 >= TILDA && LA39_6 <= TO)||LA39_6==URI) ) {s = 9;} + + input.seek(index39_6); + if ( s>=0 ) return s; + break; + + case 43 : + int LA39_31 = input.LA(1); + + int index39_31 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_31); + if ( s>=0 ) return s; + break; + + case 44 : + int LA39_61 = input.LA(1); + + int index39_61 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_61); + if ( s>=0 ) return s; + break; + + case 45 : + int LA39_73 = input.LA(1); + + int index39_73 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_73); + if ( s>=0 ) return s; + break; + + case 46 : + int LA39_49 = input.LA(1); + + int index39_49 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_49); + if ( s>=0 ) return s; + break; + + case 47 : + int LA39_15 = input.LA(1); + + int index39_15 = input.index(); + input.rewind(); + s = -1; + if ( (LA39_15==COLON) && (synpred18_FTS())) {s = 19;} + else if ( (LA39_15==EOF||(LA39_15 >= AMP && LA39_15 <= BAR)||LA39_15==CARAT||LA39_15==COMMA||LA39_15==DATETIME||LA39_15==DECIMAL_INTEGER_LITERAL||LA39_15==DOT||LA39_15==EQUALS||LA39_15==EXCLAMATION||LA39_15==FLOATING_POINT_LITERAL||(LA39_15 >= FTSPHRASE && LA39_15 <= FTSWORD)||LA39_15==ID||(LA39_15 >= LPAREN && LA39_15 <= LT)||LA39_15==MINUS||LA39_15==NOT||(LA39_15 >= OR && LA39_15 <= PERCENT)||LA39_15==PLUS||LA39_15==QUESTION_MARK||LA39_15==RPAREN||LA39_15==STAR||(LA39_15 >= TILDA && LA39_15 <= TO)||LA39_15==URI) ) {s = 9;} + + input.seek(index39_15); + if ( s>=0 ) return s; + break; + + case 48 : + int LA39_27 = input.LA(1); + + int index39_27 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_27); + if ( s>=0 ) return s; + break; + + case 49 : + int LA39_57 = input.LA(1); + + int index39_57 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_57); + if ( s>=0 ) return s; + break; + + case 50 : + int LA39_69 = input.LA(1); + + int index39_69 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_69); + if ( s>=0 ) return s; + break; + + case 51 : + int LA39_81 = input.LA(1); + + int index39_81 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_81); + if ( s>=0 ) return s; + break; + + case 52 : + int LA39_52 = input.LA(1); + + int index39_52 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_52); + if ( s>=0 ) return s; + break; + + case 53 : + int LA39_74 = input.LA(1); + + int index39_74 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_74); + if ( s>=0 ) return s; + break; + + case 54 : + int LA39_70 = input.LA(1); + + int index39_70 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_70); + if ( s>=0 ) return s; + break; + + case 55 : + int LA39_12 = input.LA(1); + + int index39_12 = input.index(); + input.rewind(); + s = -1; + if ( (LA39_12==DOT) ) {s = 18;} + else if ( (LA39_12==COLON) && (synpred18_FTS())) {s = 19;} + else if ( (LA39_12==EOF||(LA39_12 >= AMP && LA39_12 <= BAR)||LA39_12==CARAT||LA39_12==COMMA||LA39_12==DATETIME||LA39_12==DECIMAL_INTEGER_LITERAL||LA39_12==EQUALS||LA39_12==EXCLAMATION||LA39_12==FLOATING_POINT_LITERAL||(LA39_12 >= FTSPHRASE && LA39_12 <= FTSWORD)||LA39_12==ID||(LA39_12 >= LPAREN && LA39_12 <= LT)||LA39_12==MINUS||LA39_12==NOT||(LA39_12 >= OR && LA39_12 <= PERCENT)||LA39_12==PLUS||LA39_12==QUESTION_MARK||LA39_12==RPAREN||LA39_12==STAR||(LA39_12 >= TILDA && LA39_12 <= TO)||LA39_12==URI) ) {s = 9;} + + input.seek(index39_12); + if ( s>=0 ) return s; + break; + + case 56 : + int LA39_41 = input.LA(1); + + int index39_41 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_41); + if ( s>=0 ) return s; + break; + + case 57 : + int LA39_54 = input.LA(1); + + int index39_54 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_54); + if ( s>=0 ) return s; + break; + + case 58 : + int LA39_56 = input.LA(1); + + int index39_56 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_56); + if ( s>=0 ) return s; + break; + + case 59 : + int LA39_48 = input.LA(1); + + int index39_48 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_48); + if ( s>=0 ) return s; + break; + + case 60 : + int LA39_3 = input.LA(1); + + int index39_3 = input.index(); + input.rewind(); + s = -1; + if ( (LA39_3==COLON) && (synpred18_FTS())) {s = 11;} + else if ( (LA39_3==EOF||(LA39_3 >= AMP && LA39_3 <= BAR)||LA39_3==CARAT||LA39_3==COMMA||LA39_3==DATETIME||LA39_3==DECIMAL_INTEGER_LITERAL||LA39_3==DOT||LA39_3==EQUALS||LA39_3==EXCLAMATION||LA39_3==FLOATING_POINT_LITERAL||(LA39_3 >= FTSPHRASE && LA39_3 <= FTSWORD)||LA39_3==ID||(LA39_3 >= LPAREN && LA39_3 <= LT)||LA39_3==MINUS||LA39_3==NOT||(LA39_3 >= OR && LA39_3 <= PERCENT)||LA39_3==PLUS||LA39_3==QUESTION_MARK||LA39_3==RPAREN||LA39_3==STAR||(LA39_3 >= TILDA && LA39_3 <= TO)||LA39_3==URI) ) {s = 9;} + + input.seek(index39_3); + if ( s>=0 ) return s; + break; + + case 61 : + int LA39_46 = input.LA(1); + + int index39_46 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_46); + if ( s>=0 ) return s; + break; + + case 62 : + int LA39_33 = input.LA(1); + + int index39_33 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_33); + if ( s>=0 ) return s; + break; + + case 63 : + int LA39_65 = input.LA(1); + + int index39_65 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_65); + if ( s>=0 ) return s; + break; + + case 64 : + int LA39_77 = input.LA(1); + + int index39_77 = input.index(); + input.rewind(); + s = -1; + if ( (synpred18_FTS()) ) {s = 19;} + else if ( (true) ) {s = 9;} + + input.seek(index39_77); + if ( s>=0 ) return s; + break; + + case 65 : + int LA39_2 = input.LA(1); + + int index39_2 = input.index(); + input.rewind(); + s = -1; + if ( (LA39_2==DOT) ) {s = 10;} + else if ( (LA39_2==COLON) && (synpred18_FTS())) {s = 11;} + else if ( (LA39_2==EOF||(LA39_2 >= AMP && LA39_2 <= BAR)||LA39_2==CARAT||LA39_2==COMMA||LA39_2==DATETIME||LA39_2==DECIMAL_INTEGER_LITERAL||LA39_2==EQUALS||LA39_2==EXCLAMATION||LA39_2==FLOATING_POINT_LITERAL||(LA39_2 >= FTSPHRASE && LA39_2 <= FTSWORD)||LA39_2==ID||(LA39_2 >= LPAREN && LA39_2 <= LT)||LA39_2==MINUS||LA39_2==NOT||(LA39_2 >= OR && LA39_2 <= PERCENT)||LA39_2==PLUS||LA39_2==QUESTION_MARK||LA39_2==RPAREN||LA39_2==STAR||(LA39_2 >= TILDA && LA39_2 <= TO)||LA39_2==URI) ) {s = 9;} + + input.seek(index39_2); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 39, _s, input); + error(nvae); + throw nvae; + } + } + + static final String DFA60_eotS = + "\u00bb\uffff"; + static final String DFA60_eofS = + "\u00bb\uffff"; + static final String DFA60_minS = + "\1\13\12\4\1\5\2\uffff\1\13\1\4\1\13\3\uffff\1\4\34\uffff\5\4\70\uffff"+ + "\1\4\12\0\1\5\6\uffff\2\4\32\uffff\6\0\14\uffff\1\4\12\uffff\1\0\1\uffff"; + static final String DFA60_maxS = + "\13\150\1\146\2\uffff\3\150\3\uffff\1\150\34\uffff\5\150\70\uffff\1\150"+ + "\12\0\1\146\6\uffff\2\150\32\uffff\6\0\14\uffff\1\150\12\uffff\1\0\1\uffff"; + static final String DFA60_acceptS = + "\14\uffff\2\2\3\uffff\2\10\1\11\1\uffff\33\2\1\10\5\uffff\15\3\1\5\34"+ + "\4\1\6\15\7\14\uffff\6\2\2\uffff\1\1\31\2\6\uffff\14\2\1\uffff\12\2\1"+ + "\uffff\1\2"; + static final String DFA60_specialS = + "\1\16\1\4\1\12\1\20\1\14\1\40\1\50\1\30\1\44\1\1\1\47\3\uffff\1\41\1\2"+ + "\1\10\3\uffff\1\5\34\uffff\1\22\1\26\1\32\1\31\1\45\70\uffff\1\0\1\3\1"+ + "\7\1\33\1\46\1\21\1\36\1\15\1\11\1\42\1\25\7\uffff\1\35\1\27\32\uffff"+ + "\1\43\1\24\1\37\1\6\1\13\1\34\14\uffff\1\17\12\uffff\1\23\1\uffff}>"; + static final String[] DFA60_transitionS = { + "\1\14\1\uffff\1\11\1\uffff\1\7\5\uffff\1\14\2\uffff\1\16\26\uffff\1\10"+ + "\2\uffff\1\17\1\3\1\4\1\2\11\uffff\1\1\3\uffff\1\23\1\21\1\22\10\uffff"+ + "\1\5\11\uffff\1\15\7\uffff\1\12\4\uffff\1\20\1\6\1\uffff\1\13", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\25\1\60\1\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2\uffff"+ + "\1\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff\1\57"+ + "\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32\4\uffff"+ + "\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\25\1\60\1\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2\uffff"+ + "\1\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff\1\57"+ + "\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32\4\uffff"+ + "\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\25\1\60\1\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2\uffff"+ + "\1\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff\1\57"+ + "\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32\4\uffff"+ + "\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\25\1\60\1\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2\uffff"+ + "\1\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff\1\57"+ + "\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32\4\uffff"+ + "\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\25\2\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2\uffff\1"+ + "\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff\1\57"+ + "\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32\4\uffff"+ + "\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\25\2\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2\uffff\1"+ + "\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff\1\57"+ + "\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32\4\uffff"+ + "\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\25\1\60\1\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2\uffff"+ + "\1\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff\1\57"+ + "\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32\4\uffff"+ + "\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\25\1\60\1\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2\uffff"+ + "\1\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff\1\57"+ + "\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32\4\uffff"+ + "\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\25\1\60\1\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2\uffff"+ + "\1\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff\1\57"+ + "\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32\4\uffff"+ + "\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\25\1\60\1\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2\uffff"+ + "\1\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff\1\57"+ + "\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32\4\uffff"+ + "\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "\1\64\71\uffff\1\61\16\uffff\1\65\2\uffff\1\63\24\uffff\1\62", + "", + "", + "\1\66\1\uffff\1\101\1\uffff\1\75\5\uffff\1\66\2\uffff\1\103\26\uffff"+ + "\1\76\3\uffff\1\71\1\72\1\70\11\uffff\1\67\16\uffff\1\73\11\uffff\1\100"+ + "\7\uffff\1\77\5\uffff\1\74\1\uffff\1\102", + "\1\107\1\106\1\uffff\1\112\1\uffff\1\105\1\uffff\1\127\1\uffff\1\124"+ + "\1\uffff\1\122\5\uffff\1\127\1\60\1\uffff\1\131\2\uffff\1\120\23\uffff"+ + "\1\123\2\uffff\1\132\1\116\1\117\1\115\11\uffff\1\114\3\uffff\1\135\1"+ + "\133\1\134\2\uffff\1\137\5\uffff\1\113\2\uffff\1\111\2\uffff\1\136\3"+ + "\uffff\1\130\2\uffff\1\110\4\uffff\1\125\4\uffff\1\104\1\121\1\uffff"+ + "\1\126", + "\1\141\1\uffff\1\154\1\uffff\1\150\5\uffff\1\141\2\uffff\1\140\26\uffff"+ + "\1\151\3\uffff\1\144\1\145\1\143\11\uffff\1\142\16\uffff\1\146\11\uffff"+ + "\1\153\7\uffff\1\152\5\uffff\1\147\1\uffff\1\155", + "", + "", + "", + "\1\176\1\175\1\uffff\1\34\1\uffff\1\174\1\uffff\1\172\1\uffff\1\167"+ + "\1\uffff\1\165\5\uffff\1\172\1\177\1\uffff\1\51\2\uffff\1\42\23\uffff"+ + "\1\166\2\uffff\1\52\1\161\1\162\1\160\11\uffff\1\157\3\uffff\1\156\1"+ + "\53\1\54\2\uffff\1\57\5\uffff\1\163\2\uffff\1\33\2\uffff\1\56\3\uffff"+ + "\1\50\2\uffff\1\32\4\uffff\1\170\4\uffff\1\173\1\164\1\uffff\1\171", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\u0080\1\60\1\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2"+ + "\uffff\1\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff"+ + "\1\57\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32"+ + "\4\uffff\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\25\1\60\1\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2\uffff"+ + "\1\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff\1\57"+ + "\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32\4\uffff"+ + "\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\25\1\60\1\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2\uffff"+ + "\1\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff\1\57"+ + "\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32\4\uffff"+ + "\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\25\1\60\1\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2\uffff"+ + "\1\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff\1\57"+ + "\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32\4\uffff"+ + "\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\25\1\uffff\1\46\1\uffff"+ + "\1\44\5\uffff\1\25\1\60\1\uffff\1\51\2\uffff\1\42\23\uffff\1\45\2\uffff"+ + "\1\52\1\40\1\41\1\37\11\uffff\1\36\3\uffff\1\55\1\53\1\54\2\uffff\1\57"+ + "\5\uffff\1\35\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2\uffff\1\32\4\uffff"+ + "\1\24\4\uffff\1\26\1\43\1\uffff\1\47", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\u0084\1\u0083\1\uffff\1\u0099\3\uffff\1\u0090\1\uffff\1\u008d\1\uffff"+ + "\1\u0081\5\uffff\1\u0090\2\uffff\1\u0092\2\uffff\1\u008a\23\uffff\1\u008c"+ + "\2\uffff\1\u0093\1\u0088\1\u0089\1\u0087\11\uffff\1\u0086\3\uffff\1\u0097"+ + "\1\u0095\1\u0096\2\uffff\1\u009a\5\uffff\1\u0085\2\uffff\1\u009b\2\uffff"+ + "\1\u0098\3\uffff\1\u0091\2\uffff\1\u0082\4\uffff\1\u008e\4\uffff\1\u0094"+ + "\1\u008b\1\uffff\1\u008f", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\u009f\71\uffff\1\u009c\16\uffff\1\u00a0\2\uffff\1\u009e\24\uffff"+ + "\1\u009d", + "", + "", + "", + "", + "", + "", + "\1\31\1\30\1\uffff\1\34\1\uffff\1\27\1\uffff\1\u00ad\1\uffff\1\u00ab"+ + "\1\uffff\1\u00a7\5\uffff\1\u00ad\2\uffff\1\51\2\uffff\1\42\23\uffff\1"+ + "\u00a8\2\uffff\1\52\1\u00a3\1\u00a4\1\u00a2\11\uffff\1\u00a1\3\uffff"+ + "\1\55\1\53\1\54\2\uffff\1\57\5\uffff\1\u00a5\2\uffff\1\33\2\uffff\1\56"+ + "\3\uffff\1\u00aa\2\uffff\1\32\4\uffff\1\u00a9\4\uffff\1\26\1\u00a6\1"+ + "\uffff\1\u00ac", + "\1\u00b6\1\u00b5\1\uffff\1\u00b4\1\uffff\1\u00b2\1\uffff\1\u00b0\1\uffff"+ + "\1\u008d\1\uffff\1\u00b7\5\uffff\1\u00b0\1\u00b8\1\uffff\1\u0092\2\uffff"+ + "\1\u008a\23\uffff\1\u008c\2\uffff\1\u0093\1\u0088\1\u0089\1\u0087\11"+ + "\uffff\1\u0086\3\uffff\1\u0097\1\u0095\1\u0096\2\uffff\1\u009a\5\uffff"+ + "\1\u0085\2\uffff\1\u00b3\2\uffff\1\u0098\3\uffff\1\u0091\2\uffff\1\u00ae"+ + "\4\uffff\1\u00af\4\uffff\1\u00b1\1\u008b\1\uffff\1\u008f", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\176\1\175\1\uffff\1\34\1\uffff\1\174\1\uffff\1\u00ad\1\uffff\1\167"+ + "\1\uffff\1\165\5\uffff\1\u00ad\2\uffff\1\51\2\uffff\1\42\23\uffff\1\166"+ + "\2\uffff\1\52\1\161\1\162\1\160\11\uffff\1\157\3\uffff\1\55\1\53\1\54"+ + "\2\uffff\1\57\5\uffff\1\163\2\uffff\1\33\2\uffff\1\56\3\uffff\1\50\2"+ + "\uffff\1\32\4\uffff\1\u00b9\4\uffff\1\u00ba\1\164\1\uffff\1\171", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\uffff", + "" + }; + + static final short[] DFA60_eot = DFA.unpackEncodedString(DFA60_eotS); + static final short[] DFA60_eof = DFA.unpackEncodedString(DFA60_eofS); + static final char[] DFA60_min = DFA.unpackEncodedStringToUnsignedChars(DFA60_minS); + static final char[] DFA60_max = DFA.unpackEncodedStringToUnsignedChars(DFA60_maxS); + static final short[] DFA60_accept = DFA.unpackEncodedString(DFA60_acceptS); + static final short[] DFA60_special = DFA.unpackEncodedString(DFA60_specialS); + static final short[][] DFA60_transition; + + static { + int numStates = DFA60_transitionS.length; + DFA60_transition = new short[numStates][]; + for (int i=0; i ftsFieldGroupProximity -> ^( FG_PROXIMITY ftsFieldGroupProximity ) | ( ftsFieldGroupTerm )=> ftsFieldGroupTerm ( ( fuzzy )=> fuzzy )? -> ^( FG_TERM ftsFieldGroupTerm ( fuzzy )? ) | ( ftsFieldGroupExactTerm )=> ftsFieldGroupExactTerm ( ( fuzzy )=> fuzzy )? -> ^( FG_EXACT_TERM ftsFieldGroupExactTerm ( fuzzy )? ) | ( ftsFieldGroupPhrase )=> ftsFieldGroupPhrase ( ( slop )=> slop )? -> ^( FG_PHRASE ftsFieldGroupPhrase ( slop )? ) | ( ftsFieldGroupExactPhrase )=> ftsFieldGroupExactPhrase ( ( slop )=> slop )? -> ^( FG_EXACT_PHRASE ftsFieldGroupExactPhrase ( slop )? ) | ( ftsFieldGroupTokenisedPhrase )=> ftsFieldGroupTokenisedPhrase ( ( slop )=> slop )? -> ^( FG_PHRASE ftsFieldGroupTokenisedPhrase ( slop )? ) | ( ftsFieldGroupSynonym )=> ftsFieldGroupSynonym ( ( fuzzy )=> fuzzy )? -> ^( FG_SYNONYM ftsFieldGroupSynonym ( fuzzy )? ) | ( ftsFieldGroupRange )=> ftsFieldGroupRange -> ^( FG_RANGE ftsFieldGroupRange ) | LPAREN ftsFieldGroupDisjunction RPAREN -> ftsFieldGroupDisjunction );"; + } + @Override + public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { + TokenStream input = (TokenStream)_input; + int _s = s; + switch ( s ) { + case 0 : + int LA60_110 = input.LA(1); + + int index60_110 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_110==DECIMAL_INTEGER_LITERAL) ) {s = 129;} + else if ( (LA60_110==RPAREN) && (synpred24_FTS())) {s = 130;} + else if ( (LA60_110==AND) && (synpred25_FTS())) {s = 131;} + else if ( (LA60_110==AMP) && (synpred25_FTS())) {s = 132;} + else if ( (LA60_110==NOT) && (synpred25_FTS())) {s = 133;} + else if ( (LA60_110==ID) && (synpred25_FTS())) {s = 134;} + else if ( (LA60_110==FTSWORD) && (synpred25_FTS())) {s = 135;} + else if ( (LA60_110==FTSPRE) && (synpred25_FTS())) {s = 136;} + else if ( (LA60_110==FTSWILD) && (synpred25_FTS())) {s = 137;} + else if ( (LA60_110==EXCLAMATION) && (synpred25_FTS())) {s = 138;} + else if ( (LA60_110==TO) && (synpred25_FTS())) {s = 139;} + else if ( (LA60_110==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 140;} + else if ( (LA60_110==DATETIME) && (synpred25_FTS())) {s = 141;} + else if ( (LA60_110==STAR) && (synpred25_FTS())) {s = 142;} + else if ( (LA60_110==URI) && (synpred25_FTS())) {s = 143;} + else if ( (LA60_110==COMMA||LA60_110==DOT) && (synpred25_FTS())) {s = 144;} + else if ( (LA60_110==QUESTION_MARK) && (synpred25_FTS())) {s = 145;} + else if ( (LA60_110==EQUALS) && (synpred25_FTS())) {s = 146;} + else if ( (LA60_110==FTSPHRASE) && (synpred25_FTS())) {s = 147;} + else if ( (LA60_110==TILDA) && (synpred25_FTS())) {s = 148;} + else if ( (LA60_110==LSQUARE) && (synpred25_FTS())) {s = 149;} + else if ( (LA60_110==LT) && (synpred25_FTS())) {s = 150;} + else if ( (LA60_110==LPAREN) && (synpred25_FTS())) {s = 151;} + else if ( (LA60_110==PLUS) && (synpred25_FTS())) {s = 152;} + else if ( (LA60_110==BAR) && (synpred25_FTS())) {s = 153;} + else if ( (LA60_110==MINUS) && (synpred25_FTS())) {s = 154;} + else if ( (LA60_110==OR) && (synpred25_FTS())) {s = 155;} + + input.seek(index60_110); + if ( s>=0 ) return s; + break; + + case 1 : + int LA60_9 = input.LA(1); + + int index60_9 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_9==STAR) ) {s = 20;} + else if ( (LA60_9==COMMA||LA60_9==DOT) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_9==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_9==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_9==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_9==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_9==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_9==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_9==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_9==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_9==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_9==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_9==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_9==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_9==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_9==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_9==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_9==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_9==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_9==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_9==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_9==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_9==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_9==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_9==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_9==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_9==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_9==MINUS) && (synpred25_FTS())) {s = 47;} + else if ( (LA60_9==DOTDOT) && (synpred37_FTS())) {s = 48;} + + input.seek(index60_9); + if ( s>=0 ) return s; + break; + + case 2 : + int LA60_15 = input.LA(1); + + int index60_15 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_15==TILDA) && (synpred29_FTS())) {s = 68;} + else if ( (LA60_15==CARAT) && (synpred29_FTS())) {s = 69;} + else if ( (LA60_15==AND) && (synpred29_FTS())) {s = 70;} + else if ( (LA60_15==AMP) && (synpred29_FTS())) {s = 71;} + else if ( (LA60_15==RPAREN) && (synpred29_FTS())) {s = 72;} + else if ( (LA60_15==OR) && (synpred29_FTS())) {s = 73;} + else if ( (LA60_15==BAR) && (synpred29_FTS())) {s = 74;} + else if ( (LA60_15==NOT) && (synpred29_FTS())) {s = 75;} + else if ( (LA60_15==ID) && (synpred29_FTS())) {s = 76;} + else if ( (LA60_15==FTSWORD) && (synpred29_FTS())) {s = 77;} + else if ( (LA60_15==FTSPRE) && (synpred29_FTS())) {s = 78;} + else if ( (LA60_15==FTSWILD) && (synpred29_FTS())) {s = 79;} + else if ( (LA60_15==EXCLAMATION) && (synpred29_FTS())) {s = 80;} + else if ( (LA60_15==TO) && (synpred29_FTS())) {s = 81;} + else if ( (LA60_15==DECIMAL_INTEGER_LITERAL) && (synpred29_FTS())) {s = 82;} + else if ( (LA60_15==FLOATING_POINT_LITERAL) && (synpred29_FTS())) {s = 83;} + else if ( (LA60_15==DATETIME) && (synpred29_FTS())) {s = 84;} + else if ( (LA60_15==STAR) && (synpred29_FTS())) {s = 85;} + else if ( (LA60_15==URI) && (synpred29_FTS())) {s = 86;} + else if ( (LA60_15==COMMA||LA60_15==DOT) && (synpred29_FTS())) {s = 87;} + else if ( (LA60_15==QUESTION_MARK) && (synpred29_FTS())) {s = 88;} + else if ( (LA60_15==EQUALS) && (synpred29_FTS())) {s = 89;} + else if ( (LA60_15==FTSPHRASE) && (synpred29_FTS())) {s = 90;} + else if ( (LA60_15==LSQUARE) && (synpred29_FTS())) {s = 91;} + else if ( (LA60_15==LT) && (synpred29_FTS())) {s = 92;} + else if ( (LA60_15==LPAREN) && (synpred29_FTS())) {s = 93;} + else if ( (LA60_15==PLUS) && (synpred29_FTS())) {s = 94;} + else if ( (LA60_15==MINUS) && (synpred29_FTS())) {s = 95;} + else if ( (LA60_15==DOTDOT) && (synpred37_FTS())) {s = 48;} + + input.seek(index60_15); + if ( s>=0 ) return s; + break; + + case 3 : + int LA60_111 = input.LA(1); + + int index60_111 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 155;} + + input.seek(index60_111); + if ( s>=0 ) return s; + break; + + case 4 : + int LA60_1 = input.LA(1); + + int index60_1 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_1==STAR) ) {s = 20;} + else if ( (LA60_1==COMMA||LA60_1==DOT) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_1==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_1==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_1==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_1==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_1==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_1==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_1==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_1==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_1==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_1==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_1==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_1==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_1==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_1==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_1==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_1==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_1==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_1==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_1==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_1==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_1==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_1==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_1==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_1==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_1==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_1==MINUS) && (synpred25_FTS())) {s = 47;} + else if ( (LA60_1==DOTDOT) && (synpred37_FTS())) {s = 48;} + + input.seek(index60_1); + if ( s>=0 ) return s; + break; + + case 5 : + int LA60_20 = input.LA(1); + + int index60_20 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_20==LPAREN) ) {s = 110;} + else if ( (LA60_20==ID) ) {s = 111;} + else if ( (LA60_20==FTSWORD) ) {s = 112;} + else if ( (LA60_20==FTSPRE) ) {s = 113;} + else if ( (LA60_20==FTSWILD) ) {s = 114;} + else if ( (LA60_20==NOT) ) {s = 115;} + else if ( (LA60_20==TO) ) {s = 116;} + else if ( (LA60_20==DECIMAL_INTEGER_LITERAL) ) {s = 117;} + else if ( (LA60_20==FLOATING_POINT_LITERAL) ) {s = 118;} + else if ( (LA60_20==DATETIME) ) {s = 119;} + else if ( (LA60_20==STAR) ) {s = 120;} + else if ( (LA60_20==URI) ) {s = 121;} + else if ( (LA60_20==COMMA||LA60_20==DOT) && (synpred25_FTS())) {s = 122;} + else if ( (LA60_20==TILDA) && (synpred25_FTS())) {s = 123;} + else if ( (LA60_20==CARAT) && (synpred25_FTS())) {s = 124;} + else if ( (LA60_20==AND) && (synpred25_FTS())) {s = 125;} + else if ( (LA60_20==AMP) && (synpred25_FTS())) {s = 126;} + else if ( (LA60_20==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_20==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_20==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_20==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_20==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_20==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_20==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_20==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_20==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_20==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_20==MINUS) && (synpred25_FTS())) {s = 47;} + else if ( (LA60_20==DOTDOT) && (synpred25_FTS())) {s = 127;} + + input.seek(index60_20); + if ( s>=0 ) return s; + break; + + case 6 : + int LA60_159 = input.LA(1); + + int index60_159 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 184;} + + input.seek(index60_159); + if ( s>=0 ) return s; + break; + + case 7 : + int LA60_112 = input.LA(1); + + int index60_112 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 155;} + + input.seek(index60_112); + if ( s>=0 ) return s; + break; + + case 8 : + int LA60_16 = input.LA(1); + + int index60_16 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_16==EQUALS) && (synpred33_FTS())) {s = 96;} + else if ( (LA60_16==COMMA||LA60_16==DOT) && (synpred35_FTS())) {s = 97;} + else if ( (LA60_16==ID) && (synpred35_FTS())) {s = 98;} + else if ( (LA60_16==FTSWORD) && (synpred35_FTS())) {s = 99;} + else if ( (LA60_16==FTSPRE) && (synpred35_FTS())) {s = 100;} + else if ( (LA60_16==FTSWILD) && (synpred35_FTS())) {s = 101;} + else if ( (LA60_16==NOT) && (synpred35_FTS())) {s = 102;} + else if ( (LA60_16==TO) && (synpred35_FTS())) {s = 103;} + else if ( (LA60_16==DECIMAL_INTEGER_LITERAL) && (synpred35_FTS())) {s = 104;} + else if ( (LA60_16==FLOATING_POINT_LITERAL) && (synpred35_FTS())) {s = 105;} + else if ( (LA60_16==STAR) && (synpred35_FTS())) {s = 106;} + else if ( (LA60_16==QUESTION_MARK) && (synpred35_FTS())) {s = 107;} + else if ( (LA60_16==DATETIME) && (synpred35_FTS())) {s = 108;} + else if ( (LA60_16==URI) && (synpred35_FTS())) {s = 109;} + + input.seek(index60_16); + if ( s>=0 ) return s; + break; + + case 9 : + int LA60_118 = input.LA(1); + + int index60_118 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 155;} + + input.seek(index60_118); + if ( s>=0 ) return s; + break; + + case 10 : + int LA60_2 = input.LA(1); + + int index60_2 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_2==STAR) ) {s = 20;} + else if ( (LA60_2==COMMA||LA60_2==DOT) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_2==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_2==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_2==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_2==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_2==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_2==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_2==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_2==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_2==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_2==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_2==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_2==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_2==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_2==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_2==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_2==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_2==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_2==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_2==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_2==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_2==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_2==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_2==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_2==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_2==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_2==MINUS) && (synpred25_FTS())) {s = 47;} + else if ( (LA60_2==DOTDOT) && (synpred37_FTS())) {s = 48;} + + input.seek(index60_2); + if ( s>=0 ) return s; + break; + + case 11 : + int LA60_160 = input.LA(1); + + int index60_160 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 184;} + + input.seek(index60_160); + if ( s>=0 ) return s; + break; + + case 12 : + int LA60_4 = input.LA(1); + + int index60_4 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_4==STAR) ) {s = 20;} + else if ( (LA60_4==COMMA||LA60_4==DOT) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_4==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_4==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_4==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_4==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_4==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_4==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_4==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_4==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_4==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_4==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_4==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_4==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_4==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_4==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_4==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_4==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_4==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_4==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_4==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_4==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_4==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_4==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_4==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_4==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_4==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_4==MINUS) && (synpred25_FTS())) {s = 47;} + else if ( (LA60_4==DOTDOT) && (synpred37_FTS())) {s = 48;} + + input.seek(index60_4); + if ( s>=0 ) return s; + break; + + case 13 : + int LA60_117 = input.LA(1); + + int index60_117 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 155;} + + input.seek(index60_117); + if ( s>=0 ) return s; + break; + + case 14 : + int LA60_0 = input.LA(1); + + int index60_0 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_0==ID) ) {s = 1;} + else if ( (LA60_0==FTSWORD) ) {s = 2;} + else if ( (LA60_0==FTSPRE) ) {s = 3;} + else if ( (LA60_0==FTSWILD) ) {s = 4;} + else if ( (LA60_0==NOT) ) {s = 5;} + else if ( (LA60_0==TO) ) {s = 6;} + else if ( (LA60_0==DECIMAL_INTEGER_LITERAL) ) {s = 7;} + else if ( (LA60_0==FLOATING_POINT_LITERAL) ) {s = 8;} + else if ( (LA60_0==DATETIME) ) {s = 9;} + else if ( (LA60_0==STAR) ) {s = 10;} + else if ( (LA60_0==URI) ) {s = 11;} + else if ( (LA60_0==COMMA||LA60_0==DOT) && (synpred25_FTS())) {s = 12;} + else if ( (LA60_0==QUESTION_MARK) && (synpred25_FTS())) {s = 13;} + else if ( (LA60_0==EQUALS) ) {s = 14;} + else if ( (LA60_0==FTSPHRASE) ) {s = 15;} + else if ( (LA60_0==TILDA) ) {s = 16;} + else if ( (LA60_0==LSQUARE) && (synpred37_FTS())) {s = 17;} + else if ( (LA60_0==LT) && (synpred37_FTS())) {s = 18;} + else if ( (LA60_0==LPAREN) ) {s = 19;} + + input.seek(index60_0); + if ( s>=0 ) return s; + break; + + case 15 : + int LA60_174 = input.LA(1); + + int index60_174 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_174==ID) ) {s = 111;} + else if ( (LA60_174==FTSWORD) ) {s = 112;} + else if ( (LA60_174==FTSPRE) ) {s = 113;} + else if ( (LA60_174==FTSWILD) ) {s = 114;} + else if ( (LA60_174==NOT) ) {s = 115;} + else if ( (LA60_174==TO) ) {s = 116;} + else if ( (LA60_174==DECIMAL_INTEGER_LITERAL) ) {s = 117;} + else if ( (LA60_174==FLOATING_POINT_LITERAL) ) {s = 118;} + else if ( (LA60_174==DATETIME) ) {s = 119;} + else if ( (LA60_174==STAR) ) {s = 185;} + else if ( (LA60_174==URI) ) {s = 121;} + else if ( (LA60_174==CARAT) && (synpred25_FTS())) {s = 124;} + else if ( (LA60_174==AND) && (synpred25_FTS())) {s = 125;} + else if ( (LA60_174==AMP) && (synpred25_FTS())) {s = 126;} + else if ( (LA60_174==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_174==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_174==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_174==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_174==COMMA||LA60_174==DOT) && (synpred25_FTS())) {s = 173;} + else if ( (LA60_174==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_174==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_174==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_174==TILDA) && (synpred25_FTS())) {s = 186;} + else if ( (LA60_174==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_174==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_174==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_174==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_174==MINUS) && (synpred25_FTS())) {s = 47;} + + input.seek(index60_174); + if ( s>=0 ) return s; + break; + + case 16 : + int LA60_3 = input.LA(1); + + int index60_3 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_3==STAR) ) {s = 20;} + else if ( (LA60_3==COMMA||LA60_3==DOT) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_3==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_3==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_3==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_3==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_3==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_3==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_3==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_3==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_3==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_3==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_3==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_3==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_3==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_3==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_3==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_3==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_3==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_3==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_3==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_3==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_3==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_3==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_3==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_3==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_3==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_3==MINUS) && (synpred25_FTS())) {s = 47;} + else if ( (LA60_3==DOTDOT) && (synpred37_FTS())) {s = 48;} + + input.seek(index60_3); + if ( s>=0 ) return s; + break; + + case 17 : + int LA60_115 = input.LA(1); + + int index60_115 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 155;} + + input.seek(index60_115); + if ( s>=0 ) return s; + break; + + case 18 : + int LA60_49 = input.LA(1); + + int index60_49 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_49==DOT) ) {s = 128;} + else if ( (LA60_49==STAR) ) {s = 20;} + else if ( (LA60_49==COMMA) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_49==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_49==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_49==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_49==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_49==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_49==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_49==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_49==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_49==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_49==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_49==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_49==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_49==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_49==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_49==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_49==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_49==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_49==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_49==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_49==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_49==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_49==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_49==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_49==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_49==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_49==MINUS) && (synpred25_FTS())) {s = 47;} + else if ( (LA60_49==DOTDOT) && (synpred37_FTS())) {s = 48;} + + input.seek(index60_49); + if ( s>=0 ) return s; + break; + + case 19 : + int LA60_185 = input.LA(1); + + int index60_185 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 186;} + + input.seek(index60_185); + if ( s>=0 ) return s; + break; + + case 20 : + int LA60_157 = input.LA(1); + + int index60_157 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 184;} + + input.seek(index60_157); + if ( s>=0 ) return s; + break; + + case 21 : + int LA60_120 = input.LA(1); + + int index60_120 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 155;} + + input.seek(index60_120); + if ( s>=0 ) return s; + break; + + case 22 : + int LA60_50 = input.LA(1); + + int index60_50 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_50==STAR) ) {s = 20;} + else if ( (LA60_50==COMMA||LA60_50==DOT) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_50==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_50==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_50==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_50==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_50==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_50==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_50==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_50==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_50==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_50==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_50==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_50==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_50==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_50==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_50==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_50==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_50==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_50==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_50==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_50==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_50==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_50==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_50==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_50==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_50==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_50==MINUS) && (synpred25_FTS())) {s = 47;} + else if ( (LA60_50==DOTDOT) && (synpred37_FTS())) {s = 48;} + + input.seek(index60_50); + if ( s>=0 ) return s; + break; + + case 23 : + int LA60_129 = input.LA(1); + + int index60_129 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_129==RPAREN) ) {s = 174;} + else if ( (LA60_129==STAR) && (synpred25_FTS())) {s = 175;} + else if ( (LA60_129==COMMA||LA60_129==DOT) && (synpred25_FTS())) {s = 176;} + else if ( (LA60_129==TILDA) && (synpred25_FTS())) {s = 177;} + else if ( (LA60_129==CARAT) && (synpred25_FTS())) {s = 178;} + else if ( (LA60_129==OR) && (synpred25_FTS())) {s = 179;} + else if ( (LA60_129==BAR) && (synpred25_FTS())) {s = 180;} + else if ( (LA60_129==AND) && (synpred25_FTS())) {s = 181;} + else if ( (LA60_129==AMP) && (synpred25_FTS())) {s = 182;} + else if ( (LA60_129==NOT) && (synpred25_FTS())) {s = 133;} + else if ( (LA60_129==ID) && (synpred25_FTS())) {s = 134;} + else if ( (LA60_129==FTSWORD) && (synpred25_FTS())) {s = 135;} + else if ( (LA60_129==FTSPRE) && (synpred25_FTS())) {s = 136;} + else if ( (LA60_129==FTSWILD) && (synpred25_FTS())) {s = 137;} + else if ( (LA60_129==EXCLAMATION) && (synpred25_FTS())) {s = 138;} + else if ( (LA60_129==TO) && (synpred25_FTS())) {s = 139;} + else if ( (LA60_129==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 183;} + else if ( (LA60_129==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 140;} + else if ( (LA60_129==DATETIME) && (synpred25_FTS())) {s = 141;} + else if ( (LA60_129==URI) && (synpred25_FTS())) {s = 143;} + else if ( (LA60_129==QUESTION_MARK) && (synpred25_FTS())) {s = 145;} + else if ( (LA60_129==EQUALS) && (synpred25_FTS())) {s = 146;} + else if ( (LA60_129==FTSPHRASE) && (synpred25_FTS())) {s = 147;} + else if ( (LA60_129==LSQUARE) && (synpred25_FTS())) {s = 149;} + else if ( (LA60_129==LT) && (synpred25_FTS())) {s = 150;} + else if ( (LA60_129==LPAREN) && (synpred25_FTS())) {s = 151;} + else if ( (LA60_129==PLUS) && (synpred25_FTS())) {s = 152;} + else if ( (LA60_129==MINUS) && (synpred25_FTS())) {s = 154;} + else if ( (LA60_129==DOTDOT) && (synpred25_FTS())) {s = 184;} + + input.seek(index60_129); + if ( s>=0 ) return s; + break; + + case 24 : + int LA60_7 = input.LA(1); + + int index60_7 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_7==STAR) ) {s = 20;} + else if ( (LA60_7==COMMA||LA60_7==DOT) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_7==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_7==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_7==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_7==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_7==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_7==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_7==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_7==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_7==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_7==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_7==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_7==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_7==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_7==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_7==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_7==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_7==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_7==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_7==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_7==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_7==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_7==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_7==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_7==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_7==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_7==MINUS) && (synpred25_FTS())) {s = 47;} + else if ( (LA60_7==DOTDOT) && (synpred37_FTS())) {s = 48;} + + input.seek(index60_7); + if ( s>=0 ) return s; + break; + + case 25 : + int LA60_52 = input.LA(1); + + int index60_52 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_52==STAR) ) {s = 20;} + else if ( (LA60_52==COMMA||LA60_52==DOT) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_52==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_52==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_52==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_52==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_52==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_52==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_52==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_52==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_52==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_52==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_52==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_52==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_52==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_52==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_52==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_52==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_52==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_52==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_52==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_52==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_52==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_52==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_52==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_52==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_52==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_52==MINUS) && (synpred25_FTS())) {s = 47;} + else if ( (LA60_52==DOTDOT) && (synpred37_FTS())) {s = 48;} + + input.seek(index60_52); + if ( s>=0 ) return s; + break; + + case 26 : + int LA60_51 = input.LA(1); + + int index60_51 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_51==STAR) ) {s = 20;} + else if ( (LA60_51==COMMA||LA60_51==DOT) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_51==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_51==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_51==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_51==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_51==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_51==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_51==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_51==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_51==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_51==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_51==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_51==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_51==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_51==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_51==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_51==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_51==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_51==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_51==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_51==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_51==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_51==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_51==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_51==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_51==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_51==MINUS) && (synpred25_FTS())) {s = 47;} + else if ( (LA60_51==DOTDOT) && (synpred37_FTS())) {s = 48;} + + input.seek(index60_51); + if ( s>=0 ) return s; + break; + + case 27 : + int LA60_113 = input.LA(1); + + int index60_113 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 155;} + + input.seek(index60_113); + if ( s>=0 ) return s; + break; + + case 28 : + int LA60_161 = input.LA(1); + + int index60_161 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 184;} + else if ( (synpred37_FTS()) ) {s = 48;} + + input.seek(index60_161); + if ( s>=0 ) return s; + break; + + case 29 : + int LA60_128 = input.LA(1); + + int index60_128 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_128==ID) ) {s = 161;} + else if ( (LA60_128==FTSWORD) && (synpred25_FTS())) {s = 162;} + else if ( (LA60_128==FTSPRE) && (synpred25_FTS())) {s = 163;} + else if ( (LA60_128==FTSWILD) && (synpred25_FTS())) {s = 164;} + else if ( (LA60_128==NOT) && (synpred25_FTS())) {s = 165;} + else if ( (LA60_128==TO) && (synpred25_FTS())) {s = 166;} + else if ( (LA60_128==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 167;} + else if ( (LA60_128==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 168;} + else if ( (LA60_128==STAR) && (synpred25_FTS())) {s = 169;} + else if ( (LA60_128==QUESTION_MARK) && (synpred25_FTS())) {s = 170;} + else if ( (LA60_128==DATETIME) && (synpred25_FTS())) {s = 171;} + else if ( (LA60_128==URI) && (synpred25_FTS())) {s = 172;} + else if ( (LA60_128==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_128==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_128==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_128==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_128==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_128==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_128==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_128==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_128==COMMA||LA60_128==DOT) && (synpred25_FTS())) {s = 173;} + else if ( (LA60_128==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_128==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_128==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_128==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_128==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_128==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_128==MINUS) && (synpred25_FTS())) {s = 47;} + + input.seek(index60_128); + if ( s>=0 ) return s; + break; + + case 30 : + int LA60_116 = input.LA(1); + + int index60_116 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 155;} + + input.seek(index60_116); + if ( s>=0 ) return s; + break; + + case 31 : + int LA60_158 = input.LA(1); + + int index60_158 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 184;} + + input.seek(index60_158); + if ( s>=0 ) return s; + break; + + case 32 : + int LA60_5 = input.LA(1); + + int index60_5 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_5==STAR) ) {s = 20;} + else if ( (LA60_5==COMMA||LA60_5==DOT) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_5==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_5==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_5==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_5==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_5==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_5==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_5==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_5==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_5==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_5==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_5==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_5==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_5==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_5==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_5==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_5==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_5==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_5==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_5==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_5==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_5==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_5==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_5==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_5==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_5==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_5==MINUS) && (synpred25_FTS())) {s = 47;} + + input.seek(index60_5); + if ( s>=0 ) return s; + break; + + case 33 : + int LA60_14 = input.LA(1); + + int index60_14 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_14==COMMA||LA60_14==DOT) && (synpred27_FTS())) {s = 54;} + else if ( (LA60_14==ID) && (synpred27_FTS())) {s = 55;} + else if ( (LA60_14==FTSWORD) && (synpred27_FTS())) {s = 56;} + else if ( (LA60_14==FTSPRE) && (synpred27_FTS())) {s = 57;} + else if ( (LA60_14==FTSWILD) && (synpred27_FTS())) {s = 58;} + else if ( (LA60_14==NOT) && (synpred27_FTS())) {s = 59;} + else if ( (LA60_14==TO) && (synpred27_FTS())) {s = 60;} + else if ( (LA60_14==DECIMAL_INTEGER_LITERAL) && (synpred27_FTS())) {s = 61;} + else if ( (LA60_14==FLOATING_POINT_LITERAL) && (synpred27_FTS())) {s = 62;} + else if ( (LA60_14==STAR) && (synpred27_FTS())) {s = 63;} + else if ( (LA60_14==QUESTION_MARK) && (synpred27_FTS())) {s = 64;} + else if ( (LA60_14==DATETIME) && (synpred27_FTS())) {s = 65;} + else if ( (LA60_14==URI) && (synpred27_FTS())) {s = 66;} + else if ( (LA60_14==EQUALS) && (synpred31_FTS())) {s = 67;} + + input.seek(index60_14); + if ( s>=0 ) return s; + break; + + case 34 : + int LA60_119 = input.LA(1); + + int index60_119 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 155;} + + input.seek(index60_119); + if ( s>=0 ) return s; + break; + + case 35 : + int LA60_156 = input.LA(1); + + int index60_156 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 184;} + + input.seek(index60_156); + if ( s>=0 ) return s; + break; + + case 36 : + int LA60_8 = input.LA(1); + + int index60_8 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_8==STAR) ) {s = 20;} + else if ( (LA60_8==COMMA||LA60_8==DOT) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_8==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_8==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_8==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_8==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_8==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_8==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_8==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_8==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_8==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_8==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_8==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_8==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_8==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_8==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_8==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_8==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_8==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_8==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_8==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_8==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_8==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_8==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_8==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_8==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_8==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_8==MINUS) && (synpred25_FTS())) {s = 47;} + else if ( (LA60_8==DOTDOT) && (synpred37_FTS())) {s = 48;} + + input.seek(index60_8); + if ( s>=0 ) return s; + break; + + case 37 : + int LA60_53 = input.LA(1); + + int index60_53 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_53==STAR) ) {s = 20;} + else if ( (LA60_53==COMMA||LA60_53==DOT) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_53==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_53==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_53==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_53==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_53==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_53==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_53==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_53==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_53==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_53==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_53==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_53==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_53==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_53==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_53==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_53==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_53==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_53==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_53==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_53==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_53==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_53==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_53==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_53==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_53==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_53==MINUS) && (synpred25_FTS())) {s = 47;} + else if ( (LA60_53==DOTDOT) && (synpred37_FTS())) {s = 48;} + + input.seek(index60_53); + if ( s>=0 ) return s; + break; + + case 38 : + int LA60_114 = input.LA(1); + + int index60_114 = input.index(); + input.rewind(); + s = -1; + if ( (synpred24_FTS()) ) {s = 130;} + else if ( (synpred25_FTS()) ) {s = 155;} + + input.seek(index60_114); + if ( s>=0 ) return s; + break; + + case 39 : + int LA60_10 = input.LA(1); + + int index60_10 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_10==STAR) ) {s = 20;} + else if ( (LA60_10==COMMA||LA60_10==DOT) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_10==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_10==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_10==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_10==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_10==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_10==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_10==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_10==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_10==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_10==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_10==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_10==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_10==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_10==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_10==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_10==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_10==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_10==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_10==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_10==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_10==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_10==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_10==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_10==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_10==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_10==MINUS) && (synpred25_FTS())) {s = 47;} + else if ( (LA60_10==DOTDOT) && (synpred37_FTS())) {s = 48;} + + input.seek(index60_10); + if ( s>=0 ) return s; + break; + + case 40 : + int LA60_6 = input.LA(1); + + int index60_6 = input.index(); + input.rewind(); + s = -1; + if ( (LA60_6==STAR) ) {s = 20;} + else if ( (LA60_6==COMMA||LA60_6==DOT) && (synpred25_FTS())) {s = 21;} + else if ( (LA60_6==TILDA) && (synpred25_FTS())) {s = 22;} + else if ( (LA60_6==CARAT) && (synpred25_FTS())) {s = 23;} + else if ( (LA60_6==AND) && (synpred25_FTS())) {s = 24;} + else if ( (LA60_6==AMP) && (synpred25_FTS())) {s = 25;} + else if ( (LA60_6==RPAREN) && (synpred25_FTS())) {s = 26;} + else if ( (LA60_6==OR) && (synpred25_FTS())) {s = 27;} + else if ( (LA60_6==BAR) && (synpred25_FTS())) {s = 28;} + else if ( (LA60_6==NOT) && (synpred25_FTS())) {s = 29;} + else if ( (LA60_6==ID) && (synpred25_FTS())) {s = 30;} + else if ( (LA60_6==FTSWORD) && (synpred25_FTS())) {s = 31;} + else if ( (LA60_6==FTSPRE) && (synpred25_FTS())) {s = 32;} + else if ( (LA60_6==FTSWILD) && (synpred25_FTS())) {s = 33;} + else if ( (LA60_6==EXCLAMATION) && (synpred25_FTS())) {s = 34;} + else if ( (LA60_6==TO) && (synpred25_FTS())) {s = 35;} + else if ( (LA60_6==DECIMAL_INTEGER_LITERAL) && (synpred25_FTS())) {s = 36;} + else if ( (LA60_6==FLOATING_POINT_LITERAL) && (synpred25_FTS())) {s = 37;} + else if ( (LA60_6==DATETIME) && (synpred25_FTS())) {s = 38;} + else if ( (LA60_6==URI) && (synpred25_FTS())) {s = 39;} + else if ( (LA60_6==QUESTION_MARK) && (synpred25_FTS())) {s = 40;} + else if ( (LA60_6==EQUALS) && (synpred25_FTS())) {s = 41;} + else if ( (LA60_6==FTSPHRASE) && (synpred25_FTS())) {s = 42;} + else if ( (LA60_6==LSQUARE) && (synpred25_FTS())) {s = 43;} + else if ( (LA60_6==LT) && (synpred25_FTS())) {s = 44;} + else if ( (LA60_6==LPAREN) && (synpred25_FTS())) {s = 45;} + else if ( (LA60_6==PLUS) && (synpred25_FTS())) {s = 46;} + else if ( (LA60_6==MINUS) && (synpred25_FTS())) {s = 47;} + + input.seek(index60_6); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 60, _s, input); + error(nvae); + throw nvae; + } + } + + static final String DFA73_eotS = + "\u01ca\uffff"; + static final String DFA73_eofS = + "\2\uffff\13\33\1\uffff\13\42\1\uffff\1\70\1\uffff\5\33\1\130\1\uffff\5"+ + "\42\37\uffff\1\70\37\uffff\1\130\1\u009c\21\uffff\1\u00c1\60\uffff\1\u009c"+ + "\44\uffff\1\u00c1\5\uffff\1\u00f4\6\uffff\1\u0115\45\uffff\2\u00f4\37"+ + "\uffff\2\u0115\1\u015c\22\uffff\1\u0182\61\uffff\2\u015c\44\uffff\2\u0182"+ + "\27\uffff\1\u015c\22\uffff\1\u0182\14\uffff"; + static final String DFA73_minS = + "\1\13\1\15\13\4\1\5\13\4\1\5\1\4\1\uffff\6\4\1\uffff\5\4\13\13\1\5\23"+ + "\uffff\1\4\13\13\1\5\23\uffff\2\4\1\uffff\5\13\1\0\12\13\1\4\1\uffff\5"+ + "\13\1\0\25\13\1\5\23\uffff\1\4\5\uffff\13\13\1\5\23\uffff\1\4\5\uffff"+ + "\1\4\6\13\1\4\21\13\1\5\23\uffff\2\4\13\13\1\5\23\uffff\3\4\21\13\1\5"+ + "\1\4\21\13\1\5\13\0\1\5\23\uffff\2\4\5\13\13\0\1\5\23\uffff\2\4\5\13\21"+ + "\0\1\5\1\4\21\0\1\5\1\4\14\0"; + static final String DFA73_maxS = + "\15\150\1\146\13\150\1\146\1\150\1\uffff\6\150\1\uffff\5\150\13\25\1\146"+ + "\23\uffff\1\150\13\25\1\146\23\uffff\2\150\1\uffff\5\25\1\0\12\25\1\150"+ + "\1\uffff\5\25\1\0\25\25\1\146\23\uffff\1\150\5\uffff\13\25\1\146\23\uffff"+ + "\1\150\5\uffff\1\150\6\25\1\150\21\25\1\146\23\uffff\2\150\13\25\1\146"+ + "\23\uffff\3\150\21\25\1\146\1\150\21\25\1\146\13\0\1\146\23\uffff\2\150"+ + "\5\25\13\0\1\146\23\uffff\2\150\5\25\21\0\1\146\1\150\21\0\1\146\1\150"+ + "\14\0"; + static final String DFA73_acceptS = + "\33\uffff\1\22\6\uffff\1\21\21\uffff\23\20\15\uffff\23\17\2\uffff\1\16"+ + "\21\uffff\1\15\34\uffff\23\14\1\uffff\1\2\1\4\1\6\1\10\1\12\14\uffff\23"+ + "\13\1\uffff\1\1\1\3\1\5\1\7\1\11\32\uffff\23\10\16\uffff\23\7\64\uffff"+ + "\23\4\23\uffff\23\3\71\uffff"; + static final String DFA73_specialS = + "\32\uffff\1\52\6\uffff\1\131\6\uffff\1\14\1\46\1\40\1\121\1\21\1\u008b"+ + "\1\60\1\146\1\135\1\62\1\u00e9\24\uffff\1\u00aa\1\173\1\144\1\125\1\u0088"+ + "\1\u00b3\1\u00ee\1\151\1\132\1\u0091\1\170\1\70\24\uffff\1\u00d0\1\31"+ + "\1\uffff\1\156\1\u0087\1\u00f3\1\103\1\163\1\53\1\47\1\41\1\122\1\22\1"+ + "\u008c\1\61\1\147\1\136\1\63\1\u00ea\1\124\1\uffff\1\76\1\u00a1\1\u009a"+ + "\1\u00cc\1\20\1\u009b\1\145\1\126\1\u0089\1\u00b4\1\u00ef\1\152\1\133"+ + "\1\u0092\1\171\1\71\1\15\1\101\1\54\1\120\1\u009e\1\72\1\u00b6\1\u00cd"+ + "\1\u00ed\1\u00b1\1\12\24\uffff\1\154\5\uffff\1\u00c3\1\u00f1\1\42\1\73"+ + "\1\u00a6\1\u00e0\1\164\1\u0084\1\u00a7\1\160\1\u00e5\24\uffff\1\u00b8"+ + "\5\uffff\1\u00b7\1\u0080\1\u00eb\1\35\1\102\1\127\1\u00d8\1\1\1\u00d6"+ + "\1\165\1\u0090\1\u00ab\1\u00c7\1\u0099\1\65\1\u0094\1\u00b2\1\u00a5\1"+ + "\u00c5\1\153\1\4\1\105\1\134\1\45\1\161\24\uffff\1\u00d9\1\u00af\1\u00dd"+ + "\1\115\1\162\1\u0083\1\u00c4\1\67\1\u00e6\1\37\1\104\1\17\1\140\24\uffff"+ + "\1\100\1\u00d3\1\u0093\1\44\1\30\1\75\1\123\1\172\1\137\1\111\1\u00b9"+ + "\1\u00ca\1\u00e3\1\u00d7\1\u008d\1\56\1\117\1\155\1\u0081\1\u00b5\1\uffff"+ + "\1\0\1\u00cf\1\u00ac\1\u00c8\1\u00e7\1\27\1\u00d4\1\32\1\167\1\u0097\1"+ + "\u00b0\1\u00f0\1\143\1\u00db\1\3\1\64\1\50\1\177\1\uffff\1\u0098\1\10"+ + "\1\51\1\141\1\13\1\u00c2\1\u008a\1\u00a9\1\u00bf\1\u00de\1\33\24\uffff"+ + "\1\u00bc\1\u0082\1\u0095\1\7\1\55\1\116\1\u0096\1\113\1\u00da\1\2\1\107"+ + "\1\110\1\u00ad\1\157\1\u008e\1\u00a8\1\u00e4\1\u00ec\24\uffff\1\66\1\u00be"+ + "\1\u00df\1\u00ae\1\u00cb\1\u00e1\1\24\1\43\1\112\1\150\1\u0086\1\u00a3"+ + "\1\u00d5\1\166\1\5\1\106\1\142\1\26\1\u00ce\1\u008f\1\u00a0\1\u00c0\1"+ + "\u00dc\1\36\1\uffff\1\u009f\1\u00bd\1\25\1\77\1\130\1\174\1\u00a2\1\57"+ + "\1\u00e2\1\34\1\6\1\11\1\u0085\1\175\1\u009c\1\u00bb\1\u00c6\1\u00c1\1"+ + "\uffff\1\u00e8\1\u00a4\1\u00d1\1\u00f2\1\23\1\74\1\16\1\114\1\176\1\u009d"+ + "\1\u00ba\1\u00c9\1\u00d2}>"; + static final String[] DFA73_transitionS = { + "\1\1\1\uffff\1\14\1\uffff\1\10\5\uffff\1\1\31\uffff\1\11\3\uffff\1\4"+ + "\1\5\1\3\11\uffff\1\2\16\uffff\1\6\11\uffff\1\13\7\uffff\1\12\5\uffff"+ + "\1\7\1\uffff\1\15", + "\1\30\1\uffff\1\24\37\uffff\1\25\3\uffff\1\20\1\21\1\17\11\uffff\1\16"+ + "\16\uffff\1\22\11\uffff\1\27\7\uffff\1\26\5\uffff\1\23\1\uffff\1\31", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\1\37\71\uffff\1\34\16\uffff\1\40\2\uffff\1\36\24\uffff\1\35", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\1\46\71\uffff\1\43\16\uffff\1\47\2\uffff\1\45\24\uffff\1\44", + "\1\67\1\66\1\75\1\73\1\uffff\1\65\1\uffff\1\101\1\uffff\1\62\1\uffff"+ + "\1\56\5\uffff\1\101\2\uffff\1\102\2\uffff\1\74\23\uffff\1\57\2\uffff"+ + "\1\76\1\52\1\53\1\51\11\uffff\1\50\3\uffff\1\103\1\77\1\100\2\uffff\1"+ + "\106\5\uffff\1\54\2\uffff\1\72\1\104\1\uffff\1\105\3\uffff\1\61\2\uffff"+ + "\1\71\4\uffff\1\60\4\uffff\1\64\1\55\1\uffff\1\63", + "", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\107\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1"+ + "\33\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33"+ + "\3\uffff\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\4\33\1\uffff\1\33\1\uffff\1\32\1\uffff\1\33\1\uffff\1\33\5\uffff\1"+ + "\32\2\uffff\1\33\2\uffff\1\33\23\uffff\1\33\2\uffff\4\33\11\uffff\1\33"+ + "\3\uffff\3\33\2\uffff\1\33\5\uffff\1\33\2\uffff\2\33\1\uffff\1\33\3\uffff"+ + "\1\33\2\uffff\1\33\4\uffff\1\33\4\uffff\2\33\1\uffff\1\33", + "\1\127\1\126\1\135\1\133\1\uffff\1\125\1\uffff\1\141\1\uffff\1\122\1"+ + "\uffff\1\116\5\uffff\1\141\2\uffff\1\142\2\uffff\1\134\23\uffff\1\117"+ + "\2\uffff\1\136\1\112\1\113\1\111\11\uffff\1\110\3\uffff\1\143\1\137\1"+ + "\140\2\uffff\1\146\5\uffff\1\114\2\uffff\1\132\1\144\1\uffff\1\145\3"+ + "\uffff\1\121\2\uffff\1\131\4\uffff\1\120\4\uffff\1\124\1\115\1\uffff"+ + "\1\123", + "", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\147\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1"+ + "\42\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42"+ + "\3\uffff\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\4\42\1\uffff\1\42\1\uffff\1\41\1\uffff\1\42\1\uffff\1\42\5\uffff\1"+ + "\41\2\uffff\1\42\2\uffff\1\42\23\uffff\1\42\2\uffff\4\42\11\uffff\1\42"+ + "\3\uffff\3\42\2\uffff\1\42\5\uffff\1\42\2\uffff\2\42\1\uffff\1\42\3\uffff"+ + "\1\42\2\uffff\1\42\4\uffff\1\42\4\uffff\2\42\1\uffff\1\42", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\155\71\uffff\1\152\16\uffff\1\156\2\uffff\1\154\24\uffff\1\153", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\67\1\66\1\75\1\73\1\uffff\1\65\1\uffff\1\101\1\uffff\1\171\1\uffff"+ + "\1\165\5\uffff\1\101\2\uffff\1\102\2\uffff\1\74\23\uffff\1\166\2\uffff"+ + "\1\76\1\161\1\162\1\160\11\uffff\1\157\3\uffff\1\103\1\77\1\100\2\uffff"+ + "\1\106\5\uffff\1\163\2\uffff\1\72\1\104\1\uffff\1\105\3\uffff\1\170\2"+ + "\uffff\1\71\4\uffff\1\167\4\uffff\1\64\1\164\1\uffff\1\63", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\177\71\uffff\1\174\16\uffff\1\u0080\2\uffff\1\176\24\uffff\1\175", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\127\1\126\1\135\1\133\1\uffff\1\125\1\uffff\1\141\1\uffff\1\u008b"+ + "\1\uffff\1\u0087\5\uffff\1\141\2\uffff\1\142\2\uffff\1\134\23\uffff\1"+ + "\u0088\2\uffff\1\136\1\u0083\1\u0084\1\u0082\11\uffff\1\u0081\3\uffff"+ + "\1\143\1\137\1\140\2\uffff\1\146\5\uffff\1\u0085\2\uffff\1\132\1\144"+ + "\1\uffff\1\145\3\uffff\1\u008a\2\uffff\1\131\4\uffff\1\u0089\4\uffff"+ + "\1\124\1\u0086\1\uffff\1\123", + "\1\u009b\1\u009a\1\u00a1\1\u009f\1\uffff\1\u0099\1\uffff\1\u00a5\1\uffff"+ + "\1\u0096\1\uffff\1\u0092\5\uffff\1\u00a5\2\uffff\1\u00a6\2\uffff\1\u00a0"+ + "\23\uffff\1\u0093\2\uffff\1\u00a2\1\u008e\1\u008f\1\u008d\11\uffff\1"+ + "\u008c\3\uffff\1\u00a7\1\u00a3\1\u00a4\2\uffff\1\u00aa\5\uffff\1\u0090"+ + "\2\uffff\1\u009e\1\u00a8\1\uffff\1\u00a9\3\uffff\1\u0095\2\uffff\1\u009d"+ + "\4\uffff\1\u0094\4\uffff\1\u0098\1\u0091\1\uffff\1\u0097", + "", + "\1\150\11\uffff\1\u00ab", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\uffff", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\150\11\uffff\1\150", + "\1\u00c0\1\u00bf\1\u00c6\1\u00c4\1\uffff\1\u00be\1\uffff\1\u00ca\1\uffff"+ + "\1\u00bb\1\uffff\1\u00b7\5\uffff\1\u00ca\2\uffff\1\u00cb\2\uffff\1\u00c5"+ + "\23\uffff\1\u00b8\2\uffff\1\u00c7\1\u00b3\1\u00b4\1\u00b2\11\uffff\1"+ + "\u00b1\3\uffff\1\u00cc\1\u00c8\1\u00c9\2\uffff\1\u00cf\5\uffff\1\u00b5"+ + "\2\uffff\1\u00c3\1\u00cd\1\uffff\1\u00ce\3\uffff\1\u00ba\2\uffff\1\u00c2"+ + "\4\uffff\1\u00b9\4\uffff\1\u00bd\1\u00b6\1\uffff\1\u00bc", + "", + "\1\172\11\uffff\1\u00d0", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\uffff", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\172\11\uffff\1\172", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u00da\71\uffff\1\u00d7\16\uffff\1\u00db\2\uffff\1\u00d9\24\uffff"+ + "\1\u00d8", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\u009b\1\u009a\1\u00a1\1\u009f\1\uffff\1\u0099\1\uffff\1\u00a5\1\uffff"+ + "\1\u0096\1\uffff\1\u0092\5\uffff\1\u00a5\2\uffff\1\u00a6\2\uffff\1\u00a0"+ + "\23\uffff\1\u0093\2\uffff\1\u00a2\1\u008e\1\u008f\1\u008d\11\uffff\1"+ + "\u00dc\3\uffff\1\u00a7\1\u00a3\1\u00a4\2\uffff\1\u00aa\5\uffff\1\u0090"+ + "\2\uffff\1\u009e\1\u00a8\1\uffff\1\u00a9\3\uffff\1\u0095\2\uffff\1\u009d"+ + "\4\uffff\1\u0094\4\uffff\1\u0098\1\u0091\1\uffff\1\u0097", + "", + "", + "", + "", + "", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u00e1\71\uffff\1\u00de\16\uffff\1\u00e2\2\uffff\1\u00e0\24\uffff"+ + "\1\u00df", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\u00c0\1\u00bf\1\u00c6\1\u00c4\1\uffff\1\u00be\1\uffff\1\u00ca\1\uffff"+ + "\1\u00bb\1\uffff\1\u00b7\5\uffff\1\u00ca\2\uffff\1\u00cb\2\uffff\1\u00c5"+ + "\23\uffff\1\u00b8\2\uffff\1\u00c7\1\u00b3\1\u00b4\1\u00b2\11\uffff\1"+ + "\u00e3\3\uffff\1\u00cc\1\u00c8\1\u00c9\2\uffff\1\u00cf\5\uffff\1\u00b5"+ + "\2\uffff\1\u00c3\1\u00cd\1\uffff\1\u00ce\3\uffff\1\u00ba\2\uffff\1\u00c2"+ + "\4\uffff\1\u00b9\4\uffff\1\u00bd\1\u00b6\1\uffff\1\u00bc", + "", + "", + "", + "", + "", + "\1\u00f3\1\u00f2\1\u00f9\1\u00f7\1\uffff\1\u00f1\1\uffff\1\u00fd\1\uffff"+ + "\1\u00ee\1\uffff\1\u00ea\5\uffff\1\u00fd\2\uffff\1\u00fe\2\uffff\1\u00f8"+ + "\23\uffff\1\u00eb\2\uffff\1\u00fa\1\u00e6\1\u00e7\1\u00e5\11\uffff\1"+ + "\u00e4\3\uffff\1\u00ff\1\u00fb\1\u00fc\2\uffff\1\u0102\5\uffff\1\u00e8"+ + "\2\uffff\1\u00f6\1\u0100\1\uffff\1\u0101\3\uffff\1\u00ed\2\uffff\1\u00f5"+ + "\4\uffff\1\u00ec\4\uffff\1\u00f0\1\u00e9\1\uffff\1\u00ef", + "\1\u00d6\11\uffff\1\u0103", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u00d6\11\uffff\1\u00d6", + "\1\u0104\11\uffff\1\u0104", + "\1\u0114\1\u0113\1\u011a\1\u0118\1\uffff\1\u0112\1\uffff\1\u011e\1\uffff"+ + "\1\u010f\1\uffff\1\u010b\5\uffff\1\u011e\2\uffff\1\u011f\2\uffff\1\u0119"+ + "\23\uffff\1\u010c\2\uffff\1\u011b\1\u0107\1\u0108\1\u0106\11\uffff\1"+ + "\u0105\3\uffff\1\u0120\1\u011c\1\u011d\2\uffff\1\u0123\5\uffff\1\u0109"+ + "\2\uffff\1\u0117\1\u0121\1\uffff\1\u0122\3\uffff\1\u010e\2\uffff\1\u0116"+ + "\4\uffff\1\u010d\4\uffff\1\u0111\1\u010a\1\uffff\1\u0110", + "\1\u00dd\11\uffff\1\u0124", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u00dd\11\uffff\1\u00dd", + "\1\u0125\11\uffff\1\u0125", + "\1\u0126\11\uffff\1\u0126", + "\1\u0126\11\uffff\1\u0126", + "\1\u0126\11\uffff\1\u0126", + "\1\u0126\11\uffff\1\u0126", + "\1\u0126\11\uffff\1\u0126", + "\1\u0126\11\uffff\1\u0126", + "\1\u0126\11\uffff\1\u0126", + "\1\u0126\11\uffff\1\u0126", + "\1\u0126\11\uffff\1\u0126", + "\1\u0126\11\uffff\1\u0126", + "\1\u0126\11\uffff\1\u0126", + "\1\u012a\71\uffff\1\u0127\16\uffff\1\u012b\2\uffff\1\u0129\24\uffff"+ + "\1\u0128", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\u00f3\1\u00f2\1\u00f9\1\u00f7\1\uffff\1\u00f1\1\uffff\1\u00fd\1\uffff"+ + "\1\u00ee\1\uffff\1\u00ea\5\uffff\1\u00fd\2\uffff\1\u00fe\2\uffff\1\u00f8"+ + "\23\uffff\1\u00eb\2\uffff\1\u00fa\1\u00e6\1\u00e7\1\u00e5\11\uffff\1"+ + "\u012c\3\uffff\1\u00ff\1\u00fb\1\u00fc\2\uffff\1\u0102\5\uffff\1\u00e8"+ + "\2\uffff\1\u00f6\1\u0100\1\uffff\1\u0101\3\uffff\1\u00ed\2\uffff\1\u00f5"+ + "\4\uffff\1\u00ec\4\uffff\1\u00f0\1\u00e9\1\uffff\1\u00ef", + "\1\u00f3\1\u00f2\1\u00f9\1\u00f7\1\uffff\1\u00f1\1\uffff\1\u00fd\1\uffff"+ + "\1\u0137\1\uffff\1\u0133\5\uffff\1\u00fd\2\uffff\1\u00fe\2\uffff\1\u00f8"+ + "\23\uffff\1\u0134\2\uffff\1\u00fa\1\u012f\1\u0130\1\u012e\11\uffff\1"+ + "\u012d\3\uffff\1\u00ff\1\u00fb\1\u00fc\2\uffff\1\u0102\5\uffff\1\u0131"+ + "\2\uffff\1\u00f6\1\u0100\1\uffff\1\u0101\3\uffff\1\u0136\2\uffff\1\u00f5"+ + "\4\uffff\1\u0135\4\uffff\1\u00f0\1\u0132\1\uffff\1\u0138", + "\1\u0139\11\uffff\1\u0139", + "\1\u0139\11\uffff\1\u0139", + "\1\u0139\11\uffff\1\u0139", + "\1\u0139\11\uffff\1\u0139", + "\1\u0139\11\uffff\1\u0139", + "\1\u0139\11\uffff\1\u0139", + "\1\u0139\11\uffff\1\u0139", + "\1\u0139\11\uffff\1\u0139", + "\1\u0139\11\uffff\1\u0139", + "\1\u0139\11\uffff\1\u0139", + "\1\u0139\11\uffff\1\u0139", + "\1\u013d\71\uffff\1\u013a\16\uffff\1\u013e\2\uffff\1\u013c\24\uffff"+ + "\1\u013b", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\u0114\1\u0113\1\u011a\1\u0118\1\uffff\1\u0112\1\uffff\1\u011e\1\uffff"+ + "\1\u010f\1\uffff\1\u010b\5\uffff\1\u011e\2\uffff\1\u011f\2\uffff\1\u0119"+ + "\23\uffff\1\u010c\2\uffff\1\u011b\1\u0107\1\u0108\1\u0106\11\uffff\1"+ + "\u013f\3\uffff\1\u0120\1\u011c\1\u011d\2\uffff\1\u0123\5\uffff\1\u0109"+ + "\2\uffff\1\u0117\1\u0121\1\uffff\1\u0122\3\uffff\1\u010e\2\uffff\1\u0116"+ + "\4\uffff\1\u010d\4\uffff\1\u0111\1\u010a\1\uffff\1\u0110", + "\1\u0114\1\u0113\1\u011a\1\u0118\1\uffff\1\u0112\1\uffff\1\u011e\1\uffff"+ + "\1\u014a\1\uffff\1\u0146\5\uffff\1\u011e\2\uffff\1\u011f\2\uffff\1\u0119"+ + "\23\uffff\1\u0147\2\uffff\1\u011b\1\u0142\1\u0143\1\u0141\11\uffff\1"+ + "\u0140\3\uffff\1\u0120\1\u011c\1\u011d\2\uffff\1\u0123\5\uffff\1\u0144"+ + "\2\uffff\1\u0117\1\u0121\1\uffff\1\u0122\3\uffff\1\u0149\2\uffff\1\u0116"+ + "\4\uffff\1\u0148\4\uffff\1\u0111\1\u0145\1\uffff\1\u014b", + "\1\u015b\1\u015a\1\u0161\1\u015f\1\uffff\1\u0159\1\uffff\1\u0165\1\uffff"+ + "\1\u0156\1\uffff\1\u0152\5\uffff\1\u0165\2\uffff\1\u0166\2\uffff\1\u0160"+ + "\23\uffff\1\u0153\2\uffff\1\u0162\1\u014e\1\u014f\1\u014d\11\uffff\1"+ + "\u014c\3\uffff\1\u0167\1\u0163\1\u0164\2\uffff\1\u016a\5\uffff\1\u0150"+ + "\2\uffff\1\u015e\1\u0168\1\uffff\1\u0169\3\uffff\1\u0155\2\uffff\1\u015d"+ + "\4\uffff\1\u0154\4\uffff\1\u0158\1\u0151\1\uffff\1\u0157", + "\1\u0126\11\uffff\1\u016b", + "\1\u0126\11\uffff\1\u0126", + "\1\u0126\11\uffff\1\u0126", + "\1\u0126\11\uffff\1\u0126", + "\1\u0126\11\uffff\1\u0126", + "\1\u016c\11\uffff\1\u016c", + "\1\u016c\11\uffff\1\u016c", + "\1\u016c\11\uffff\1\u016c", + "\1\u016c\11\uffff\1\u016c", + "\1\u016c\11\uffff\1\u016c", + "\1\u016c\11\uffff\1\u016c", + "\1\u016c\11\uffff\1\u016c", + "\1\u016c\11\uffff\1\u016c", + "\1\u016c\11\uffff\1\u016c", + "\1\u016c\11\uffff\1\u016c", + "\1\u016c\11\uffff\1\u016c", + "\1\u016c\11\uffff\1\u016c", + "\1\u0170\71\uffff\1\u016d\16\uffff\1\u0171\2\uffff\1\u016f\24\uffff"+ + "\1\u016e", + "\1\u0181\1\u0180\1\u0187\1\u0185\1\uffff\1\u017f\1\uffff\1\u018b\1\uffff"+ + "\1\u017c\1\uffff\1\u0178\5\uffff\1\u018b\2\uffff\1\u018c\2\uffff\1\u0186"+ + "\23\uffff\1\u0179\2\uffff\1\u0188\1\u0174\1\u0175\1\u0173\11\uffff\1"+ + "\u0172\3\uffff\1\u018d\1\u0189\1\u018a\2\uffff\1\u0190\5\uffff\1\u0176"+ + "\2\uffff\1\u0184\1\u018e\1\uffff\1\u018f\3\uffff\1\u017b\2\uffff\1\u0183"+ + "\4\uffff\1\u017a\4\uffff\1\u017e\1\u0177\1\uffff\1\u017d", + "\1\u0139\11\uffff\1\u0191", + "\1\u0139\11\uffff\1\u0139", + "\1\u0139\11\uffff\1\u0139", + "\1\u0139\11\uffff\1\u0139", + "\1\u0139\11\uffff\1\u0139", + "\1\u0192\11\uffff\1\u0192", + "\1\u0192\11\uffff\1\u0192", + "\1\u0192\11\uffff\1\u0192", + "\1\u0192\11\uffff\1\u0192", + "\1\u0192\11\uffff\1\u0192", + "\1\u0192\11\uffff\1\u0192", + "\1\u0192\11\uffff\1\u0192", + "\1\u0192\11\uffff\1\u0192", + "\1\u0192\11\uffff\1\u0192", + "\1\u0192\11\uffff\1\u0192", + "\1\u0192\11\uffff\1\u0192", + "\1\u0192\11\uffff\1\u0192", + "\1\u0196\71\uffff\1\u0193\16\uffff\1\u0197\2\uffff\1\u0195\24\uffff"+ + "\1\u0194", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\u019b\71\uffff\1\u0198\16\uffff\1\u019c\2\uffff\1\u019a\24\uffff"+ + "\1\u0199", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\u015b\1\u015a\1\u0161\1\u015f\1\uffff\1\u0159\1\uffff\1\u0165\1\uffff"+ + "\1\u0156\1\uffff\1\u0152\5\uffff\1\u0165\2\uffff\1\u0166\2\uffff\1\u0160"+ + "\23\uffff\1\u0153\2\uffff\1\u0162\1\u014e\1\u014f\1\u014d\11\uffff\1"+ + "\u019d\3\uffff\1\u0167\1\u0163\1\u0164\2\uffff\1\u016a\5\uffff\1\u0150"+ + "\2\uffff\1\u015e\1\u0168\1\uffff\1\u0169\3\uffff\1\u0155\2\uffff\1\u015d"+ + "\4\uffff\1\u0154\4\uffff\1\u0158\1\u0151\1\uffff\1\u0157", + "\1\u015b\1\u015a\1\u0161\1\u015f\1\uffff\1\u0159\1\uffff\1\u0165\1\uffff"+ + "\1\u01a8\1\uffff\1\u01a4\5\uffff\1\u0165\2\uffff\1\u0166\2\uffff\1\u0160"+ + "\23\uffff\1\u01a5\2\uffff\1\u0162\1\u01a0\1\u01a1\1\u019f\11\uffff\1"+ + "\u019e\3\uffff\1\u0167\1\u0163\1\u0164\2\uffff\1\u016a\5\uffff\1\u01a2"+ + "\2\uffff\1\u015e\1\u0168\1\uffff\1\u0169\3\uffff\1\u01a7\2\uffff\1\u015d"+ + "\4\uffff\1\u01a6\4\uffff\1\u0158\1\u01a3\1\uffff\1\u01a9", + "\1\u016c\11\uffff\1\u01aa", + "\1\u016c\11\uffff\1\u016c", + "\1\u016c\11\uffff\1\u016c", + "\1\u016c\11\uffff\1\u016c", + "\1\u016c\11\uffff\1\u016c", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\u01ae\71\uffff\1\u01ab\16\uffff\1\u01af\2\uffff\1\u01ad\24\uffff"+ + "\1\u01ac", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\1\u0181\1\u0180\1\u0187\1\u0185\1\uffff\1\u017f\1\uffff\1\u018b\1\uffff"+ + "\1\u017c\1\uffff\1\u0178\5\uffff\1\u018b\2\uffff\1\u018c\2\uffff\1\u0186"+ + "\23\uffff\1\u0179\2\uffff\1\u0188\1\u0174\1\u0175\1\u0173\11\uffff\1"+ + "\u01b0\3\uffff\1\u018d\1\u0189\1\u018a\2\uffff\1\u0190\5\uffff\1\u0176"+ + "\2\uffff\1\u0184\1\u018e\1\uffff\1\u018f\3\uffff\1\u017b\2\uffff\1\u0183"+ + "\4\uffff\1\u017a\4\uffff\1\u017e\1\u0177\1\uffff\1\u017d", + "\1\u0181\1\u0180\1\u0187\1\u0185\1\uffff\1\u017f\1\uffff\1\u018b\1\uffff"+ + "\1\u01bb\1\uffff\1\u01b7\5\uffff\1\u018b\2\uffff\1\u018c\2\uffff\1\u0186"+ + "\23\uffff\1\u01b8\2\uffff\1\u0188\1\u01b3\1\u01b4\1\u01b2\11\uffff\1"+ + "\u01b1\3\uffff\1\u018d\1\u0189\1\u018a\2\uffff\1\u0190\5\uffff\1\u01b5"+ + "\2\uffff\1\u0184\1\u018e\1\uffff\1\u018f\3\uffff\1\u01ba\2\uffff\1\u0183"+ + "\4\uffff\1\u01b9\4\uffff\1\u017e\1\u01b6\1\uffff\1\u01bc", + "\1\u0192\11\uffff\1\u01bd", + "\1\u0192\11\uffff\1\u0192", + "\1\u0192\11\uffff\1\u0192", + "\1\u0192\11\uffff\1\u0192", + "\1\u0192\11\uffff\1\u0192", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\u01c1\71\uffff\1\u01be\16\uffff\1\u01c2\2\uffff\1\u01c0\24\uffff"+ + "\1\u01bf", + "\1\u015b\1\u015a\1\u0161\1\u015f\1\uffff\1\u0159\1\uffff\1\u0165\1\uffff"+ + "\1\u01a8\1\uffff\1\u01a4\5\uffff\1\u0165\2\uffff\1\u0166\2\uffff\1\u0160"+ + "\23\uffff\1\u01a5\2\uffff\1\u0162\1\u01a0\1\u01a1\1\u019f\11\uffff\1"+ + "\u01c3\3\uffff\1\u0167\1\u0163\1\u0164\2\uffff\1\u016a\5\uffff\1\u01a2"+ + "\2\uffff\1\u015e\1\u0168\1\uffff\1\u0169\3\uffff\1\u01a7\2\uffff\1\u015d"+ + "\4\uffff\1\u01a6\4\uffff\1\u0158\1\u01a3\1\uffff\1\u01a9", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\u01c7\71\uffff\1\u01c4\16\uffff\1\u01c8\2\uffff\1\u01c6\24\uffff"+ + "\1\u01c5", + "\1\u0181\1\u0180\1\u0187\1\u0185\1\uffff\1\u017f\1\uffff\1\u018b\1\uffff"+ + "\1\u01bb\1\uffff\1\u01b7\5\uffff\1\u018b\2\uffff\1\u018c\2\uffff\1\u0186"+ + "\23\uffff\1\u01b8\2\uffff\1\u0188\1\u01b3\1\u01b4\1\u01b2\11\uffff\1"+ + "\u01c9\3\uffff\1\u018d\1\u0189\1\u018a\2\uffff\1\u0190\5\uffff\1\u01b5"+ + "\2\uffff\1\u0184\1\u018e\1\uffff\1\u018f\3\uffff\1\u01ba\2\uffff\1\u0183"+ + "\4\uffff\1\u01b9\4\uffff\1\u017e\1\u01b6\1\uffff\1\u01bc", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff", + "\1\uffff" + }; + + static final short[] DFA73_eot = DFA.unpackEncodedString(DFA73_eotS); + static final short[] DFA73_eof = DFA.unpackEncodedString(DFA73_eofS); + static final char[] DFA73_min = DFA.unpackEncodedStringToUnsignedChars(DFA73_minS); + static final char[] DFA73_max = DFA.unpackEncodedStringToUnsignedChars(DFA73_maxS); + static final short[] DFA73_accept = DFA.unpackEncodedString(DFA73_acceptS); + static final short[] DFA73_special = DFA.unpackEncodedString(DFA73_specialS); + static final short[][] DFA73_transition; + + static { + int numStates = DFA73_transitionS.length; + DFA73_transition = new short[numStates][]; + for (int i=0; i ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase DOT | COMMA ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ftsWordBase ( DOT | COMMA ) ftsWordBase )=> ftsWordBase ( DOT | COMMA ) ftsWordBase | ( ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) )=> ( DOT | COMMA ) ftsWordBase ( DOT | COMMA ) | ( ftsWordBase ( DOT | COMMA ) )=> ftsWordBase ( DOT | COMMA ) | ( DOT | COMMA ) ftsWordBase | ftsWordBase );"; + } + @Override + public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { + TokenStream input = (TokenStream)_input; + int _s = s; + switch ( s ) { + case 0 : + int LA73_313 = input.LA(1); + + int index73_313 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_313==ID) ) {s = 370;} + else if ( (LA73_313==FTSWORD) ) {s = 371;} + else if ( (LA73_313==FTSPRE) ) {s = 372;} + else if ( (LA73_313==FTSWILD) ) {s = 373;} + else if ( (LA73_313==NOT) ) {s = 374;} + else if ( (LA73_313==TO) ) {s = 375;} + else if ( (LA73_313==DECIMAL_INTEGER_LITERAL) ) {s = 376;} + else if ( (LA73_313==FLOATING_POINT_LITERAL) ) {s = 377;} + else if ( (LA73_313==STAR) ) {s = 378;} + else if ( (LA73_313==QUESTION_MARK) ) {s = 379;} + else if ( (LA73_313==DATETIME) ) {s = 380;} + else if ( (LA73_313==URI) ) {s = 381;} + else if ( (LA73_313==TILDA) && (synpred43_FTS())) {s = 382;} + else if ( (LA73_313==CARAT) && (synpred43_FTS())) {s = 383;} + else if ( (LA73_313==AND) && (synpred43_FTS())) {s = 384;} + else if ( (LA73_313==AMP) && (synpred43_FTS())) {s = 385;} + else if ( (LA73_313==EOF) && (synpred43_FTS())) {s = 386;} + else if ( (LA73_313==RPAREN) && (synpred43_FTS())) {s = 387;} + else if ( (LA73_313==OR) && (synpred43_FTS())) {s = 388;} + else if ( (LA73_313==BAR) && (synpred43_FTS())) {s = 389;} + else if ( (LA73_313==EXCLAMATION) && (synpred43_FTS())) {s = 390;} + else if ( (LA73_313==AT) && (synpred43_FTS())) {s = 391;} + else if ( (LA73_313==FTSPHRASE) && (synpred43_FTS())) {s = 392;} + else if ( (LA73_313==LSQUARE) && (synpred43_FTS())) {s = 393;} + else if ( (LA73_313==LT) && (synpred43_FTS())) {s = 394;} + else if ( (LA73_313==COMMA||LA73_313==DOT) && (synpred43_FTS())) {s = 395;} + else if ( (LA73_313==EQUALS) && (synpred43_FTS())) {s = 396;} + else if ( (LA73_313==LPAREN) && (synpred43_FTS())) {s = 397;} + else if ( (LA73_313==PERCENT) && (synpred43_FTS())) {s = 398;} + else if ( (LA73_313==PLUS) && (synpred43_FTS())) {s = 399;} + else if ( (LA73_313==MINUS) && (synpred43_FTS())) {s = 400;} + + input.seek(index73_313); + if ( s>=0 ) return s; + break; + + case 1 : + int LA73_221 = input.LA(1); + + int index73_221 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_221==ID) ) {s = 261;} + else if ( (LA73_221==FTSWORD) ) {s = 262;} + else if ( (LA73_221==FTSPRE) ) {s = 263;} + else if ( (LA73_221==FTSWILD) ) {s = 264;} + else if ( (LA73_221==NOT) ) {s = 265;} + else if ( (LA73_221==TO) ) {s = 266;} + else if ( (LA73_221==DECIMAL_INTEGER_LITERAL) ) {s = 267;} + else if ( (LA73_221==FLOATING_POINT_LITERAL) ) {s = 268;} + else if ( (LA73_221==STAR) ) {s = 269;} + else if ( (LA73_221==QUESTION_MARK) ) {s = 270;} + else if ( (LA73_221==DATETIME) ) {s = 271;} + else if ( (LA73_221==URI) ) {s = 272;} + else if ( (LA73_221==TILDA) && (synpred47_FTS())) {s = 273;} + else if ( (LA73_221==CARAT) && (synpred47_FTS())) {s = 274;} + else if ( (LA73_221==AND) && (synpred47_FTS())) {s = 275;} + else if ( (LA73_221==AMP) && (synpred47_FTS())) {s = 276;} + else if ( (LA73_221==EOF) && (synpred47_FTS())) {s = 277;} + else if ( (LA73_221==RPAREN) && (synpred47_FTS())) {s = 278;} + else if ( (LA73_221==OR) && (synpred47_FTS())) {s = 279;} + else if ( (LA73_221==BAR) && (synpred47_FTS())) {s = 280;} + else if ( (LA73_221==EXCLAMATION) && (synpred47_FTS())) {s = 281;} + else if ( (LA73_221==AT) && (synpred47_FTS())) {s = 282;} + else if ( (LA73_221==FTSPHRASE) && (synpred47_FTS())) {s = 283;} + else if ( (LA73_221==LSQUARE) && (synpred47_FTS())) {s = 284;} + else if ( (LA73_221==LT) && (synpred47_FTS())) {s = 285;} + else if ( (LA73_221==COMMA||LA73_221==DOT) && (synpred47_FTS())) {s = 286;} + else if ( (LA73_221==EQUALS) && (synpred47_FTS())) {s = 287;} + else if ( (LA73_221==LPAREN) && (synpred47_FTS())) {s = 288;} + else if ( (LA73_221==PERCENT) && (synpred47_FTS())) {s = 289;} + else if ( (LA73_221==PLUS) && (synpred47_FTS())) {s = 290;} + else if ( (LA73_221==MINUS) && (synpred47_FTS())) {s = 291;} + + input.seek(index73_221); + if ( s>=0 ) return s; + break; + + case 2 : + int LA73_372 = input.LA(1); + + int index73_372 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_372); + if ( s>=0 ) return s; + break; + + case 3 : + int LA73_327 = input.LA(1); + + int index73_327 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_327==COMMA||LA73_327==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_327); + if ( s>=0 ) return s; + break; + + case 4 : + int LA73_234 = input.LA(1); + + int index73_234 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_234==COMMA||LA73_234==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_234); + if ( s>=0 ) return s; + break; + + case 5 : + int LA73_415 = input.LA(1); + + int index73_415 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_415); + if ( s>=0 ) return s; + break; + + case 6 : + int LA73_436 = input.LA(1); + + int index73_436 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_436); + if ( s>=0 ) return s; + break; + + case 7 : + int LA73_366 = input.LA(1); + + int index73_366 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_366==COMMA||LA73_366==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_366); + if ( s>=0 ) return s; + break; + + case 8 : + int LA73_333 = input.LA(1); + + int index73_333 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_333); + if ( s>=0 ) return s; + break; + + case 9 : + int LA73_437 = input.LA(1); + + int index73_437 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_437); + if ( s>=0 ) return s; + break; + + case 10 : + int LA73_150 = input.LA(1); + + int index73_150 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_150==COMMA||LA73_150==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_150); + if ( s>=0 ) return s; + break; + + case 11 : + int LA73_336 = input.LA(1); + + int index73_336 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_336); + if ( s>=0 ) return s; + break; + + case 12 : + int LA73_40 = input.LA(1); + + int index73_40 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_40==COMMA||LA73_40==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_40); + if ( s>=0 ) return s; + break; + + case 13 : + int LA73_140 = input.LA(1); + + int index73_140 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_140==COMMA||LA73_140==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_140); + if ( s>=0 ) return s; + break; + + case 14 : + int LA73_451 = input.LA(1); + + int index73_451 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_451); + if ( s>=0 ) return s; + break; + + case 15 : + int LA73_270 = input.LA(1); + + int index73_270 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_270==COMMA||LA73_270==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_270); + if ( s>=0 ) return s; + break; + + case 16 : + int LA73_128 = input.LA(1); + + int index73_128 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_128==COMMA||LA73_128==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_128); + if ( s>=0 ) return s; + break; + + case 17 : + int LA73_44 = input.LA(1); + + int index73_44 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_44==COMMA||LA73_44==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_44); + if ( s>=0 ) return s; + break; + + case 18 : + int LA73_115 = input.LA(1); + + int index73_115 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_115==COMMA||LA73_115==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_115); + if ( s>=0 ) return s; + break; + + case 19 : + int LA73_449 = input.LA(1); + + int index73_449 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_449); + if ( s>=0 ) return s; + break; + + case 20 : + int LA73_407 = input.LA(1); + + int index73_407 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_407==COMMA||LA73_407==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_407); + if ( s>=0 ) return s; + break; + + case 21 : + int LA73_428 = input.LA(1); + + int index73_428 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_428); + if ( s>=0 ) return s; + break; + + case 22 : + int LA73_418 = input.LA(1); + + int index73_418 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_418); + if ( s>=0 ) return s; + break; + + case 23 : + int LA73_318 = input.LA(1); + + int index73_318 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_318==COMMA||LA73_318==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_318); + if ( s>=0 ) return s; + break; + + case 24 : + int LA73_296 = input.LA(1); + + int index73_296 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_296==COMMA||LA73_296==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_296); + if ( s>=0 ) return s; + break; + + case 25 : + int LA73_104 = input.LA(1); + + int index73_104 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_104==ID) ) {s = 140;} + else if ( (LA73_104==FTSWORD) ) {s = 141;} + else if ( (LA73_104==FTSPRE) ) {s = 142;} + else if ( (LA73_104==FTSWILD) ) {s = 143;} + else if ( (LA73_104==NOT) ) {s = 144;} + else if ( (LA73_104==TO) ) {s = 145;} + else if ( (LA73_104==DECIMAL_INTEGER_LITERAL) ) {s = 146;} + else if ( (LA73_104==FLOATING_POINT_LITERAL) ) {s = 147;} + else if ( (LA73_104==STAR) ) {s = 148;} + else if ( (LA73_104==QUESTION_MARK) ) {s = 149;} + else if ( (LA73_104==DATETIME) ) {s = 150;} + else if ( (LA73_104==URI) ) {s = 151;} + else if ( (LA73_104==TILDA) && (synpred52_FTS())) {s = 152;} + else if ( (LA73_104==CARAT) && (synpred52_FTS())) {s = 153;} + else if ( (LA73_104==AND) && (synpred52_FTS())) {s = 154;} + else if ( (LA73_104==AMP) && (synpred52_FTS())) {s = 155;} + else if ( (LA73_104==EOF) && (synpred52_FTS())) {s = 156;} + else if ( (LA73_104==RPAREN) && (synpred52_FTS())) {s = 157;} + else if ( (LA73_104==OR) && (synpred52_FTS())) {s = 158;} + else if ( (LA73_104==BAR) && (synpred52_FTS())) {s = 159;} + else if ( (LA73_104==EXCLAMATION) && (synpred52_FTS())) {s = 160;} + else if ( (LA73_104==AT) && (synpred52_FTS())) {s = 161;} + else if ( (LA73_104==FTSPHRASE) && (synpred52_FTS())) {s = 162;} + else if ( (LA73_104==LSQUARE) && (synpred52_FTS())) {s = 163;} + else if ( (LA73_104==LT) && (synpred52_FTS())) {s = 164;} + else if ( (LA73_104==COMMA||LA73_104==DOT) && (synpred52_FTS())) {s = 165;} + else if ( (LA73_104==EQUALS) && (synpred52_FTS())) {s = 166;} + else if ( (LA73_104==LPAREN) && (synpred52_FTS())) {s = 167;} + else if ( (LA73_104==PERCENT) && (synpred52_FTS())) {s = 168;} + else if ( (LA73_104==PLUS) && (synpred52_FTS())) {s = 169;} + else if ( (LA73_104==MINUS) && (synpred52_FTS())) {s = 170;} + + input.seek(index73_104); + if ( s>=0 ) return s; + break; + + case 26 : + int LA73_320 = input.LA(1); + + int index73_320 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_320==COMMA||LA73_320==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_320); + if ( s>=0 ) return s; + break; + + case 27 : + int LA73_342 = input.LA(1); + + int index73_342 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_342); + if ( s>=0 ) return s; + break; + + case 28 : + int LA73_435 = input.LA(1); + + int index73_435 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_435); + if ( s>=0 ) return s; + break; + + case 29 : + int LA73_217 = input.LA(1); + + int index73_217 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_217==COMMA||LA73_217==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_217); + if ( s>=0 ) return s; + break; + + case 30 : + int LA73_424 = input.LA(1); + + int index73_424 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_424); + if ( s>=0 ) return s; + break; + + case 31 : + int LA73_268 = input.LA(1); + + int index73_268 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_268==COMMA||LA73_268==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_268); + if ( s>=0 ) return s; + break; + + case 32 : + int LA73_42 = input.LA(1); + + int index73_42 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_42==COMMA||LA73_42==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_42); + if ( s>=0 ) return s; + break; + + case 33 : + int LA73_113 = input.LA(1); + + int index73_113 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_113==COMMA||LA73_113==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_113); + if ( s>=0 ) return s; + break; + + case 34 : + int LA73_179 = input.LA(1); + + int index73_179 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_179==COMMA||LA73_179==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_179); + if ( s>=0 ) return s; + break; + + case 35 : + int LA73_408 = input.LA(1); + + int index73_408 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_408); + if ( s>=0 ) return s; + break; + + case 36 : + int LA73_295 = input.LA(1); + + int index73_295 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_295==DOT) ) {s = 363;} + else if ( (LA73_295==COMMA) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_295); + if ( s>=0 ) return s; + break; + + case 37 : + int LA73_237 = input.LA(1); + + int index73_237 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_237==COMMA||LA73_237==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_237); + if ( s>=0 ) return s; + break; + + case 38 : + int LA73_41 = input.LA(1); + + int index73_41 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_41==COMMA||LA73_41==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_41); + if ( s>=0 ) return s; + break; + + case 39 : + int LA73_112 = input.LA(1); + + int index73_112 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_112==COMMA||LA73_112==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_112); + if ( s>=0 ) return s; + break; + + case 40 : + int LA73_329 = input.LA(1); + + int index73_329 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_329==COMMA||LA73_329==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_329); + if ( s>=0 ) return s; + break; + + case 41 : + int LA73_334 = input.LA(1); + + int index73_334 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_334); + if ( s>=0 ) return s; + break; + + case 42 : + int LA73_26 = input.LA(1); + + int index73_26 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_26==ID) ) {s = 40;} + else if ( (LA73_26==FTSWORD) ) {s = 41;} + else if ( (LA73_26==FTSPRE) ) {s = 42;} + else if ( (LA73_26==FTSWILD) ) {s = 43;} + else if ( (LA73_26==NOT) ) {s = 44;} + else if ( (LA73_26==TO) ) {s = 45;} + else if ( (LA73_26==DECIMAL_INTEGER_LITERAL) ) {s = 46;} + else if ( (LA73_26==FLOATING_POINT_LITERAL) ) {s = 47;} + else if ( (LA73_26==STAR) ) {s = 48;} + else if ( (LA73_26==QUESTION_MARK) ) {s = 49;} + else if ( (LA73_26==DATETIME) ) {s = 50;} + else if ( (LA73_26==URI) ) {s = 51;} + else if ( (LA73_26==TILDA) && (synpred56_FTS())) {s = 52;} + else if ( (LA73_26==CARAT) && (synpred56_FTS())) {s = 53;} + else if ( (LA73_26==AND) && (synpred56_FTS())) {s = 54;} + else if ( (LA73_26==AMP) && (synpred56_FTS())) {s = 55;} + else if ( (LA73_26==EOF) && (synpred56_FTS())) {s = 56;} + else if ( (LA73_26==RPAREN) && (synpred56_FTS())) {s = 57;} + else if ( (LA73_26==OR) && (synpred56_FTS())) {s = 58;} + else if ( (LA73_26==BAR) && (synpred56_FTS())) {s = 59;} + else if ( (LA73_26==EXCLAMATION) && (synpred56_FTS())) {s = 60;} + else if ( (LA73_26==AT) && (synpred56_FTS())) {s = 61;} + else if ( (LA73_26==FTSPHRASE) && (synpred56_FTS())) {s = 62;} + else if ( (LA73_26==LSQUARE) && (synpred56_FTS())) {s = 63;} + else if ( (LA73_26==LT) && (synpred56_FTS())) {s = 64;} + else if ( (LA73_26==COMMA||LA73_26==DOT) && (synpred56_FTS())) {s = 65;} + else if ( (LA73_26==EQUALS) && (synpred56_FTS())) {s = 66;} + else if ( (LA73_26==LPAREN) && (synpred56_FTS())) {s = 67;} + else if ( (LA73_26==PERCENT) && (synpred56_FTS())) {s = 68;} + else if ( (LA73_26==PLUS) && (synpred56_FTS())) {s = 69;} + else if ( (LA73_26==MINUS) && (synpred56_FTS())) {s = 70;} + + input.seek(index73_26); + if ( s>=0 ) return s; + break; + + case 43 : + int LA73_111 = input.LA(1); + + int index73_111 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 173;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 175;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_111); + if ( s>=0 ) return s; + break; + + case 44 : + int LA73_142 = input.LA(1); + + int index73_142 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_142==COMMA||LA73_142==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_142); + if ( s>=0 ) return s; + break; + + case 45 : + int LA73_367 = input.LA(1); + + int index73_367 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_367==COMMA||LA73_367==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_367); + if ( s>=0 ) return s; + break; + + case 46 : + int LA73_307 = input.LA(1); + + int index73_307 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_307==COMMA||LA73_307==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_307); + if ( s>=0 ) return s; + break; + + case 47 : + int LA73_433 = input.LA(1); + + int index73_433 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_433); + if ( s>=0 ) return s; + break; + + case 48 : + int LA73_46 = input.LA(1); + + int index73_46 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_46==COMMA||LA73_46==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_46); + if ( s>=0 ) return s; + break; + + case 49 : + int LA73_117 = input.LA(1); + + int index73_117 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_117==COMMA||LA73_117==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_117); + if ( s>=0 ) return s; + break; + + case 50 : + int LA73_49 = input.LA(1); + + int index73_49 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_49==COMMA||LA73_49==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_49); + if ( s>=0 ) return s; + break; + + case 51 : + int LA73_120 = input.LA(1); + + int index73_120 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_120==COMMA||LA73_120==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_120); + if ( s>=0 ) return s; + break; + + case 52 : + int LA73_328 = input.LA(1); + + int index73_328 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_328==COMMA||LA73_328==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_328); + if ( s>=0 ) return s; + break; + + case 53 : + int LA73_228 = input.LA(1); + + int index73_228 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_228==COMMA||LA73_228==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_228); + if ( s>=0 ) return s; + break; + + case 54 : + int LA73_401 = input.LA(1); + + int index73_401 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_401==ID) ) {s = 432;} + else if ( (LA73_401==FTSWORD) ) {s = 371;} + else if ( (LA73_401==FTSPRE) ) {s = 372;} + else if ( (LA73_401==FTSWILD) ) {s = 373;} + else if ( (LA73_401==NOT) ) {s = 374;} + else if ( (LA73_401==TO) ) {s = 375;} + else if ( (LA73_401==DECIMAL_INTEGER_LITERAL) ) {s = 376;} + else if ( (LA73_401==FLOATING_POINT_LITERAL) ) {s = 377;} + else if ( (LA73_401==STAR) ) {s = 378;} + else if ( (LA73_401==QUESTION_MARK) ) {s = 379;} + else if ( (LA73_401==DATETIME) ) {s = 380;} + else if ( (LA73_401==URI) ) {s = 381;} + else if ( (LA73_401==TILDA) && (synpred43_FTS())) {s = 382;} + else if ( (LA73_401==CARAT) && (synpred43_FTS())) {s = 383;} + else if ( (LA73_401==AND) && (synpred43_FTS())) {s = 384;} + else if ( (LA73_401==AMP) && (synpred43_FTS())) {s = 385;} + else if ( (LA73_401==EOF) && (synpred43_FTS())) {s = 386;} + else if ( (LA73_401==RPAREN) && (synpred43_FTS())) {s = 387;} + else if ( (LA73_401==OR) && (synpred43_FTS())) {s = 388;} + else if ( (LA73_401==BAR) && (synpred43_FTS())) {s = 389;} + else if ( (LA73_401==EXCLAMATION) && (synpred43_FTS())) {s = 390;} + else if ( (LA73_401==AT) && (synpred43_FTS())) {s = 391;} + else if ( (LA73_401==FTSPHRASE) && (synpred43_FTS())) {s = 392;} + else if ( (LA73_401==LSQUARE) && (synpred43_FTS())) {s = 393;} + else if ( (LA73_401==LT) && (synpred43_FTS())) {s = 394;} + else if ( (LA73_401==COMMA||LA73_401==DOT) && (synpred43_FTS())) {s = 395;} + else if ( (LA73_401==EQUALS) && (synpred43_FTS())) {s = 396;} + else if ( (LA73_401==LPAREN) && (synpred43_FTS())) {s = 397;} + else if ( (LA73_401==PERCENT) && (synpred43_FTS())) {s = 398;} + else if ( (LA73_401==PLUS) && (synpred43_FTS())) {s = 399;} + else if ( (LA73_401==MINUS) && (synpred43_FTS())) {s = 400;} + + input.seek(index73_401); + if ( s>=0 ) return s; + break; + + case 55 : + int LA73_266 = input.LA(1); + + int index73_266 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_266==COMMA||LA73_266==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_266); + if ( s>=0 ) return s; + break; + + case 56 : + int LA73_82 = input.LA(1); + + int index73_82 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_82==COMMA||LA73_82==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_82); + if ( s>=0 ) return s; + break; + + case 57 : + int LA73_139 = input.LA(1); + + int index73_139 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_139==COMMA||LA73_139==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_139); + if ( s>=0 ) return s; + break; + + case 58 : + int LA73_145 = input.LA(1); + + int index73_145 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_145==COMMA||LA73_145==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_145); + if ( s>=0 ) return s; + break; + + case 59 : + int LA73_180 = input.LA(1); + + int index73_180 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_180==COMMA||LA73_180==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_180); + if ( s>=0 ) return s; + break; + + case 60 : + int LA73_450 = input.LA(1); + + int index73_450 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_450); + if ( s>=0 ) return s; + break; + + case 61 : + int LA73_297 = input.LA(1); + + int index73_297 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_297==COMMA||LA73_297==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_297); + if ( s>=0 ) return s; + break; + + case 62 : + int LA73_124 = input.LA(1); + + int index73_124 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_124==DOT) ) {s = 208;} + else if ( (LA73_124==COMMA) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_124); + if ( s>=0 ) return s; + break; + + case 63 : + int LA73_429 = input.LA(1); + + int index73_429 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_429); + if ( s>=0 ) return s; + break; + + case 64 : + int LA73_292 = input.LA(1); + + int index73_292 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_292==ID) ) {s = 319;} + else if ( (LA73_292==FTSWORD) ) {s = 262;} + else if ( (LA73_292==FTSPRE) ) {s = 263;} + else if ( (LA73_292==FTSWILD) ) {s = 264;} + else if ( (LA73_292==NOT) ) {s = 265;} + else if ( (LA73_292==TO) ) {s = 266;} + else if ( (LA73_292==DECIMAL_INTEGER_LITERAL) ) {s = 267;} + else if ( (LA73_292==FLOATING_POINT_LITERAL) ) {s = 268;} + else if ( (LA73_292==STAR) ) {s = 269;} + else if ( (LA73_292==QUESTION_MARK) ) {s = 270;} + else if ( (LA73_292==DATETIME) ) {s = 271;} + else if ( (LA73_292==URI) ) {s = 272;} + else if ( (LA73_292==TILDA) && (synpred47_FTS())) {s = 273;} + else if ( (LA73_292==CARAT) && (synpred47_FTS())) {s = 274;} + else if ( (LA73_292==AND) && (synpred47_FTS())) {s = 275;} + else if ( (LA73_292==AMP) && (synpred47_FTS())) {s = 276;} + else if ( (LA73_292==EOF) && (synpred47_FTS())) {s = 277;} + else if ( (LA73_292==RPAREN) && (synpred47_FTS())) {s = 278;} + else if ( (LA73_292==OR) && (synpred47_FTS())) {s = 279;} + else if ( (LA73_292==BAR) && (synpred47_FTS())) {s = 280;} + else if ( (LA73_292==EXCLAMATION) && (synpred47_FTS())) {s = 281;} + else if ( (LA73_292==AT) && (synpred47_FTS())) {s = 282;} + else if ( (LA73_292==FTSPHRASE) && (synpred47_FTS())) {s = 283;} + else if ( (LA73_292==LSQUARE) && (synpred47_FTS())) {s = 284;} + else if ( (LA73_292==LT) && (synpred47_FTS())) {s = 285;} + else if ( (LA73_292==COMMA||LA73_292==DOT) && (synpred47_FTS())) {s = 286;} + else if ( (LA73_292==EQUALS) && (synpred47_FTS())) {s = 287;} + else if ( (LA73_292==LPAREN) && (synpred47_FTS())) {s = 288;} + else if ( (LA73_292==PERCENT) && (synpred47_FTS())) {s = 289;} + else if ( (LA73_292==PLUS) && (synpred47_FTS())) {s = 290;} + else if ( (LA73_292==MINUS) && (synpred47_FTS())) {s = 291;} + + input.seek(index73_292); + if ( s>=0 ) return s; + break; + + case 65 : + int LA73_141 = input.LA(1); + + int index73_141 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_141==COMMA||LA73_141==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_141); + if ( s>=0 ) return s; + break; + + case 66 : + int LA73_218 = input.LA(1); + + int index73_218 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_218==COMMA||LA73_218==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_218); + if ( s>=0 ) return s; + break; + + case 67 : + int LA73_109 = input.LA(1); + + int index73_109 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_109==COMMA||LA73_109==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_109); + if ( s>=0 ) return s; + break; + + case 68 : + int LA73_269 = input.LA(1); + + int index73_269 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_269==COMMA||LA73_269==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_269); + if ( s>=0 ) return s; + break; + + case 69 : + int LA73_235 = input.LA(1); + + int index73_235 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_235==COMMA||LA73_235==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_235); + if ( s>=0 ) return s; + break; + + case 70 : + int LA73_416 = input.LA(1); + + int index73_416 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_416); + if ( s>=0 ) return s; + break; + + case 71 : + int LA73_373 = input.LA(1); + + int index73_373 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_373); + if ( s>=0 ) return s; + break; + + case 72 : + int LA73_374 = input.LA(1); + + int index73_374 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_374); + if ( s>=0 ) return s; + break; + + case 73 : + int LA73_301 = input.LA(1); + + int index73_301 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_301==COMMA||LA73_301==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_301); + if ( s>=0 ) return s; + break; + + case 74 : + int LA73_409 = input.LA(1); + + int index73_409 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_409); + if ( s>=0 ) return s; + break; + + case 75 : + int LA73_370 = input.LA(1); + + int index73_370 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_370); + if ( s>=0 ) return s; + break; + + case 76 : + int LA73_452 = input.LA(1); + + int index73_452 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_452); + if ( s>=0 ) return s; + break; + + case 77 : + int LA73_262 = input.LA(1); + + int index73_262 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_262==COMMA||LA73_262==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_262); + if ( s>=0 ) return s; + break; + + case 78 : + int LA73_368 = input.LA(1); + + int index73_368 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_368==COMMA||LA73_368==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_368); + if ( s>=0 ) return s; + break; + + case 79 : + int LA73_308 = input.LA(1); + + int index73_308 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_308==COMMA||LA73_308==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_308); + if ( s>=0 ) return s; + break; + + case 80 : + int LA73_143 = input.LA(1); + + int index73_143 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_143==COMMA||LA73_143==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_143); + if ( s>=0 ) return s; + break; + + case 81 : + int LA73_43 = input.LA(1); + + int index73_43 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_43==COMMA||LA73_43==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_43); + if ( s>=0 ) return s; + break; + + case 82 : + int LA73_114 = input.LA(1); + + int index73_114 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_114==COMMA||LA73_114==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_114); + if ( s>=0 ) return s; + break; + + case 83 : + int LA73_298 = input.LA(1); + + int index73_298 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_298==COMMA||LA73_298==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_298); + if ( s>=0 ) return s; + break; + + case 84 : + int LA73_122 = input.LA(1); + + int index73_122 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_122==ID) ) {s = 177;} + else if ( (LA73_122==FTSWORD) ) {s = 178;} + else if ( (LA73_122==FTSPRE) ) {s = 179;} + else if ( (LA73_122==FTSWILD) ) {s = 180;} + else if ( (LA73_122==NOT) ) {s = 181;} + else if ( (LA73_122==TO) ) {s = 182;} + else if ( (LA73_122==DECIMAL_INTEGER_LITERAL) ) {s = 183;} + else if ( (LA73_122==FLOATING_POINT_LITERAL) ) {s = 184;} + else if ( (LA73_122==STAR) ) {s = 185;} + else if ( (LA73_122==QUESTION_MARK) ) {s = 186;} + else if ( (LA73_122==DATETIME) ) {s = 187;} + else if ( (LA73_122==URI) ) {s = 188;} + else if ( (LA73_122==TILDA) && (synpred51_FTS())) {s = 189;} + else if ( (LA73_122==CARAT) && (synpred51_FTS())) {s = 190;} + else if ( (LA73_122==AND) && (synpred51_FTS())) {s = 191;} + else if ( (LA73_122==AMP) && (synpred51_FTS())) {s = 192;} + else if ( (LA73_122==EOF) && (synpred51_FTS())) {s = 193;} + else if ( (LA73_122==RPAREN) && (synpred51_FTS())) {s = 194;} + else if ( (LA73_122==OR) && (synpred51_FTS())) {s = 195;} + else if ( (LA73_122==BAR) && (synpred51_FTS())) {s = 196;} + else if ( (LA73_122==EXCLAMATION) && (synpred51_FTS())) {s = 197;} + else if ( (LA73_122==AT) && (synpred51_FTS())) {s = 198;} + else if ( (LA73_122==FTSPHRASE) && (synpred51_FTS())) {s = 199;} + else if ( (LA73_122==LSQUARE) && (synpred51_FTS())) {s = 200;} + else if ( (LA73_122==LT) && (synpred51_FTS())) {s = 201;} + else if ( (LA73_122==COMMA||LA73_122==DOT) && (synpred51_FTS())) {s = 202;} + else if ( (LA73_122==EQUALS) && (synpred51_FTS())) {s = 203;} + else if ( (LA73_122==LPAREN) && (synpred51_FTS())) {s = 204;} + else if ( (LA73_122==PERCENT) && (synpred51_FTS())) {s = 205;} + else if ( (LA73_122==PLUS) && (synpred51_FTS())) {s = 206;} + else if ( (LA73_122==MINUS) && (synpred51_FTS())) {s = 207;} + + input.seek(index73_122); + if ( s>=0 ) return s; + break; + + case 85 : + int LA73_74 = input.LA(1); + + int index73_74 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_74==COMMA||LA73_74==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_74); + if ( s>=0 ) return s; + break; + + case 86 : + int LA73_131 = input.LA(1); + + int index73_131 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_131==COMMA||LA73_131==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_131); + if ( s>=0 ) return s; + break; + + case 87 : + int LA73_219 = input.LA(1); + + int index73_219 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_219==COMMA||LA73_219==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_219); + if ( s>=0 ) return s; + break; + + case 88 : + int LA73_430 = input.LA(1); + + int index73_430 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_430); + if ( s>=0 ) return s; + break; + + case 89 : + int LA73_33 = input.LA(1); + + int index73_33 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_33==ID) ) {s = 72;} + else if ( (LA73_33==FTSWORD) ) {s = 73;} + else if ( (LA73_33==FTSPRE) ) {s = 74;} + else if ( (LA73_33==FTSWILD) ) {s = 75;} + else if ( (LA73_33==NOT) ) {s = 76;} + else if ( (LA73_33==TO) ) {s = 77;} + else if ( (LA73_33==DECIMAL_INTEGER_LITERAL) ) {s = 78;} + else if ( (LA73_33==FLOATING_POINT_LITERAL) ) {s = 79;} + else if ( (LA73_33==STAR) ) {s = 80;} + else if ( (LA73_33==QUESTION_MARK) ) {s = 81;} + else if ( (LA73_33==DATETIME) ) {s = 82;} + else if ( (LA73_33==URI) ) {s = 83;} + else if ( (LA73_33==TILDA) && (synpred55_FTS())) {s = 84;} + else if ( (LA73_33==CARAT) && (synpred55_FTS())) {s = 85;} + else if ( (LA73_33==AND) && (synpred55_FTS())) {s = 86;} + else if ( (LA73_33==AMP) && (synpred55_FTS())) {s = 87;} + else if ( (LA73_33==EOF) && (synpred55_FTS())) {s = 88;} + else if ( (LA73_33==RPAREN) && (synpred55_FTS())) {s = 89;} + else if ( (LA73_33==OR) && (synpred55_FTS())) {s = 90;} + else if ( (LA73_33==BAR) && (synpred55_FTS())) {s = 91;} + else if ( (LA73_33==EXCLAMATION) && (synpred55_FTS())) {s = 92;} + else if ( (LA73_33==AT) && (synpred55_FTS())) {s = 93;} + else if ( (LA73_33==FTSPHRASE) && (synpred55_FTS())) {s = 94;} + else if ( (LA73_33==LSQUARE) && (synpred55_FTS())) {s = 95;} + else if ( (LA73_33==LT) && (synpred55_FTS())) {s = 96;} + else if ( (LA73_33==COMMA||LA73_33==DOT) && (synpred55_FTS())) {s = 97;} + else if ( (LA73_33==EQUALS) && (synpred55_FTS())) {s = 98;} + else if ( (LA73_33==LPAREN) && (synpred55_FTS())) {s = 99;} + else if ( (LA73_33==PERCENT) && (synpred55_FTS())) {s = 100;} + else if ( (LA73_33==PLUS) && (synpred55_FTS())) {s = 101;} + else if ( (LA73_33==MINUS) && (synpred55_FTS())) {s = 102;} + + input.seek(index73_33); + if ( s>=0 ) return s; + break; + + case 90 : + int LA73_79 = input.LA(1); + + int index73_79 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_79==COMMA||LA73_79==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_79); + if ( s>=0 ) return s; + break; + + case 91 : + int LA73_136 = input.LA(1); + + int index73_136 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_136==COMMA||LA73_136==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_136); + if ( s>=0 ) return s; + break; + + case 92 : + int LA73_236 = input.LA(1); + + int index73_236 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_236==COMMA||LA73_236==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_236); + if ( s>=0 ) return s; + break; + + case 93 : + int LA73_48 = input.LA(1); + + int index73_48 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_48==COMMA||LA73_48==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_48); + if ( s>=0 ) return s; + break; + + case 94 : + int LA73_119 = input.LA(1); + + int index73_119 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_119==COMMA||LA73_119==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_119); + if ( s>=0 ) return s; + break; + + case 95 : + int LA73_300 = input.LA(1); + + int index73_300 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_300==COMMA||LA73_300==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_300); + if ( s>=0 ) return s; + break; + + case 96 : + int LA73_271 = input.LA(1); + + int index73_271 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_271==COMMA||LA73_271==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_271); + if ( s>=0 ) return s; + break; + + case 97 : + int LA73_335 = input.LA(1); + + int index73_335 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_335); + if ( s>=0 ) return s; + break; + + case 98 : + int LA73_417 = input.LA(1); + + int index73_417 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_417); + if ( s>=0 ) return s; + break; + + case 99 : + int LA73_325 = input.LA(1); + + int index73_325 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_325==COMMA||LA73_325==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_325); + if ( s>=0 ) return s; + break; + + case 100 : + int LA73_73 = input.LA(1); + + int index73_73 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_73==COMMA||LA73_73==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_73); + if ( s>=0 ) return s; + break; + + case 101 : + int LA73_130 = input.LA(1); + + int index73_130 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_130==COMMA||LA73_130==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_130); + if ( s>=0 ) return s; + break; + + case 102 : + int LA73_47 = input.LA(1); + + int index73_47 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_47==COMMA||LA73_47==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_47); + if ( s>=0 ) return s; + break; + + case 103 : + int LA73_118 = input.LA(1); + + int index73_118 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_118==COMMA||LA73_118==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_118); + if ( s>=0 ) return s; + break; + + case 104 : + int LA73_410 = input.LA(1); + + int index73_410 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_410); + if ( s>=0 ) return s; + break; + + case 105 : + int LA73_78 = input.LA(1); + + int index73_78 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_78==COMMA||LA73_78==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_78); + if ( s>=0 ) return s; + break; + + case 106 : + int LA73_135 = input.LA(1); + + int index73_135 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_135==COMMA||LA73_135==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_135); + if ( s>=0 ) return s; + break; + + case 107 : + int LA73_233 = input.LA(1); + + int index73_233 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_233==COMMA||LA73_233==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_233); + if ( s>=0 ) return s; + break; + + case 108 : + int LA73_171 = input.LA(1); + + int index73_171 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_171==ID) ) {s = 220;} + else if ( (LA73_171==FTSWORD) ) {s = 141;} + else if ( (LA73_171==FTSPRE) ) {s = 142;} + else if ( (LA73_171==FTSWILD) ) {s = 143;} + else if ( (LA73_171==NOT) ) {s = 144;} + else if ( (LA73_171==TO) ) {s = 145;} + else if ( (LA73_171==DECIMAL_INTEGER_LITERAL) ) {s = 146;} + else if ( (LA73_171==FLOATING_POINT_LITERAL) ) {s = 147;} + else if ( (LA73_171==STAR) ) {s = 148;} + else if ( (LA73_171==QUESTION_MARK) ) {s = 149;} + else if ( (LA73_171==DATETIME) ) {s = 150;} + else if ( (LA73_171==URI) ) {s = 151;} + else if ( (LA73_171==TILDA) && (synpred52_FTS())) {s = 152;} + else if ( (LA73_171==CARAT) && (synpred52_FTS())) {s = 153;} + else if ( (LA73_171==AND) && (synpred52_FTS())) {s = 154;} + else if ( (LA73_171==AMP) && (synpred52_FTS())) {s = 155;} + else if ( (LA73_171==EOF) && (synpred52_FTS())) {s = 156;} + else if ( (LA73_171==RPAREN) && (synpred52_FTS())) {s = 157;} + else if ( (LA73_171==OR) && (synpred52_FTS())) {s = 158;} + else if ( (LA73_171==BAR) && (synpred52_FTS())) {s = 159;} + else if ( (LA73_171==EXCLAMATION) && (synpred52_FTS())) {s = 160;} + else if ( (LA73_171==AT) && (synpred52_FTS())) {s = 161;} + else if ( (LA73_171==FTSPHRASE) && (synpred52_FTS())) {s = 162;} + else if ( (LA73_171==LSQUARE) && (synpred52_FTS())) {s = 163;} + else if ( (LA73_171==LT) && (synpred52_FTS())) {s = 164;} + else if ( (LA73_171==COMMA||LA73_171==DOT) && (synpred52_FTS())) {s = 165;} + else if ( (LA73_171==EQUALS) && (synpred52_FTS())) {s = 166;} + else if ( (LA73_171==LPAREN) && (synpred52_FTS())) {s = 167;} + else if ( (LA73_171==PERCENT) && (synpred52_FTS())) {s = 168;} + else if ( (LA73_171==PLUS) && (synpred52_FTS())) {s = 169;} + else if ( (LA73_171==MINUS) && (synpred52_FTS())) {s = 170;} + + input.seek(index73_171); + if ( s>=0 ) return s; + break; + + case 109 : + int LA73_309 = input.LA(1); + + int index73_309 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_309==COMMA||LA73_309==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_309); + if ( s>=0 ) return s; + break; + + case 110 : + int LA73_106 = input.LA(1); + + int index73_106 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_106==DOT) ) {s = 171;} + else if ( (LA73_106==COMMA) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_106); + if ( s>=0 ) return s; + break; + + case 111 : + int LA73_376 = input.LA(1); + + int index73_376 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_376); + if ( s>=0 ) return s; + break; + + case 112 : + int LA73_186 = input.LA(1); + + int index73_186 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_186==COMMA||LA73_186==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_186); + if ( s>=0 ) return s; + break; + + case 113 : + int LA73_238 = input.LA(1); + + int index73_238 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_238==COMMA||LA73_238==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_238); + if ( s>=0 ) return s; + break; + + case 114 : + int LA73_263 = input.LA(1); + + int index73_263 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_263==COMMA||LA73_263==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_263); + if ( s>=0 ) return s; + break; + + case 115 : + int LA73_110 = input.LA(1); + + int index73_110 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_110==COMMA||LA73_110==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_110); + if ( s>=0 ) return s; + break; + + case 116 : + int LA73_183 = input.LA(1); + + int index73_183 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_183==COMMA||LA73_183==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_183); + if ( s>=0 ) return s; + break; + + case 117 : + int LA73_223 = input.LA(1); + + int index73_223 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_223==COMMA||LA73_223==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_223); + if ( s>=0 ) return s; + break; + + case 118 : + int LA73_414 = input.LA(1); + + int index73_414 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_414); + if ( s>=0 ) return s; + break; + + case 119 : + int LA73_321 = input.LA(1); + + int index73_321 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_321==COMMA||LA73_321==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_321); + if ( s>=0 ) return s; + break; + + case 120 : + int LA73_81 = input.LA(1); + + int index73_81 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_81==COMMA||LA73_81==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_81); + if ( s>=0 ) return s; + break; + + case 121 : + int LA73_138 = input.LA(1); + + int index73_138 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_138==COMMA||LA73_138==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_138); + if ( s>=0 ) return s; + break; + + case 122 : + int LA73_299 = input.LA(1); + + int index73_299 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_299==COMMA||LA73_299==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_299); + if ( s>=0 ) return s; + break; + + case 123 : + int LA73_72 = input.LA(1); + + int index73_72 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_72==COMMA||LA73_72==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_72); + if ( s>=0 ) return s; + break; + + case 124 : + int LA73_431 = input.LA(1); + + int index73_431 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_431); + if ( s>=0 ) return s; + break; + + case 125 : + int LA73_439 = input.LA(1); + + int index73_439 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_439); + if ( s>=0 ) return s; + break; + + case 126 : + int LA73_453 = input.LA(1); + + int index73_453 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_453); + if ( s>=0 ) return s; + break; + + case 127 : + int LA73_330 = input.LA(1); + + int index73_330 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_330==COMMA||LA73_330==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_330); + if ( s>=0 ) return s; + break; + + case 128 : + int LA73_215 = input.LA(1); + + int index73_215 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_215==DOT) ) {s = 259;} + else if ( (LA73_215==COMMA) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_215); + if ( s>=0 ) return s; + break; + + case 129 : + int LA73_310 = input.LA(1); + + int index73_310 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_310==COMMA||LA73_310==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_310); + if ( s>=0 ) return s; + break; + + case 130 : + int LA73_364 = input.LA(1); + + int index73_364 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_364==ID) ) {s = 414;} + else if ( (LA73_364==FTSWORD) ) {s = 415;} + else if ( (LA73_364==FTSPRE) ) {s = 416;} + else if ( (LA73_364==FTSWILD) ) {s = 417;} + else if ( (LA73_364==NOT) ) {s = 418;} + else if ( (LA73_364==TO) ) {s = 419;} + else if ( (LA73_364==DECIMAL_INTEGER_LITERAL) ) {s = 420;} + else if ( (LA73_364==FLOATING_POINT_LITERAL) ) {s = 421;} + else if ( (LA73_364==STAR) ) {s = 422;} + else if ( (LA73_364==QUESTION_MARK) ) {s = 423;} + else if ( (LA73_364==DATETIME) ) {s = 424;} + else if ( (LA73_364==URI) ) {s = 425;} + else if ( (LA73_364==TILDA) && (synpred44_FTS())) {s = 344;} + else if ( (LA73_364==CARAT) && (synpred44_FTS())) {s = 345;} + else if ( (LA73_364==AND) && (synpred44_FTS())) {s = 346;} + else if ( (LA73_364==AMP) && (synpred44_FTS())) {s = 347;} + else if ( (LA73_364==EOF) && (synpred44_FTS())) {s = 348;} + else if ( (LA73_364==RPAREN) && (synpred44_FTS())) {s = 349;} + else if ( (LA73_364==OR) && (synpred44_FTS())) {s = 350;} + else if ( (LA73_364==BAR) && (synpred44_FTS())) {s = 351;} + else if ( (LA73_364==EXCLAMATION) && (synpred44_FTS())) {s = 352;} + else if ( (LA73_364==AT) && (synpred44_FTS())) {s = 353;} + else if ( (LA73_364==FTSPHRASE) && (synpred44_FTS())) {s = 354;} + else if ( (LA73_364==LSQUARE) && (synpred44_FTS())) {s = 355;} + else if ( (LA73_364==LT) && (synpred44_FTS())) {s = 356;} + else if ( (LA73_364==COMMA||LA73_364==DOT) && (synpred44_FTS())) {s = 357;} + else if ( (LA73_364==EQUALS) && (synpred44_FTS())) {s = 358;} + else if ( (LA73_364==LPAREN) && (synpred44_FTS())) {s = 359;} + else if ( (LA73_364==PERCENT) && (synpred44_FTS())) {s = 360;} + else if ( (LA73_364==PLUS) && (synpred44_FTS())) {s = 361;} + else if ( (LA73_364==MINUS) && (synpred44_FTS())) {s = 362;} + + input.seek(index73_364); + if ( s>=0 ) return s; + break; + + case 131 : + int LA73_264 = input.LA(1); + + int index73_264 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_264==COMMA||LA73_264==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_264); + if ( s>=0 ) return s; + break; + + case 132 : + int LA73_184 = input.LA(1); + + int index73_184 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_184==COMMA||LA73_184==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_184); + if ( s>=0 ) return s; + break; + + case 133 : + int LA73_438 = input.LA(1); + + int index73_438 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_438); + if ( s>=0 ) return s; + break; + + case 134 : + int LA73_411 = input.LA(1); + + int index73_411 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_411); + if ( s>=0 ) return s; + break; + + case 135 : + int LA73_107 = input.LA(1); + + int index73_107 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_107==COMMA||LA73_107==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_107); + if ( s>=0 ) return s; + break; + + case 136 : + int LA73_75 = input.LA(1); + + int index73_75 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_75==COMMA||LA73_75==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_75); + if ( s>=0 ) return s; + break; + + case 137 : + int LA73_132 = input.LA(1); + + int index73_132 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_132==COMMA||LA73_132==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_132); + if ( s>=0 ) return s; + break; + + case 138 : + int LA73_338 = input.LA(1); + + int index73_338 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_338); + if ( s>=0 ) return s; + break; + + case 139 : + int LA73_45 = input.LA(1); + + int index73_45 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_45==COMMA||LA73_45==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_45); + if ( s>=0 ) return s; + break; + + case 140 : + int LA73_116 = input.LA(1); + + int index73_116 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_116==COMMA||LA73_116==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_116); + if ( s>=0 ) return s; + break; + + case 141 : + int LA73_306 = input.LA(1); + + int index73_306 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_306==COMMA||LA73_306==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_306); + if ( s>=0 ) return s; + break; + + case 142 : + int LA73_377 = input.LA(1); + + int index73_377 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_377); + if ( s>=0 ) return s; + break; + + case 143 : + int LA73_420 = input.LA(1); + + int index73_420 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_420); + if ( s>=0 ) return s; + break; + + case 144 : + int LA73_224 = input.LA(1); + + int index73_224 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_224==COMMA||LA73_224==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_224); + if ( s>=0 ) return s; + break; + + case 145 : + int LA73_80 = input.LA(1); + + int index73_80 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_80==COMMA||LA73_80==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_80); + if ( s>=0 ) return s; + break; + + case 146 : + int LA73_137 = input.LA(1); + + int index73_137 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_137==COMMA||LA73_137==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_137); + if ( s>=0 ) return s; + break; + + case 147 : + int LA73_294 = input.LA(1); + + int index73_294 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_294==ID) ) {s = 332;} + else if ( (LA73_294==FTSWORD) ) {s = 333;} + else if ( (LA73_294==FTSPRE) ) {s = 334;} + else if ( (LA73_294==FTSWILD) ) {s = 335;} + else if ( (LA73_294==NOT) ) {s = 336;} + else if ( (LA73_294==TO) ) {s = 337;} + else if ( (LA73_294==DECIMAL_INTEGER_LITERAL) ) {s = 338;} + else if ( (LA73_294==FLOATING_POINT_LITERAL) ) {s = 339;} + else if ( (LA73_294==STAR) ) {s = 340;} + else if ( (LA73_294==QUESTION_MARK) ) {s = 341;} + else if ( (LA73_294==DATETIME) ) {s = 342;} + else if ( (LA73_294==URI) ) {s = 343;} + else if ( (LA73_294==TILDA) && (synpred44_FTS())) {s = 344;} + else if ( (LA73_294==CARAT) && (synpred44_FTS())) {s = 345;} + else if ( (LA73_294==AND) && (synpred44_FTS())) {s = 346;} + else if ( (LA73_294==AMP) && (synpred44_FTS())) {s = 347;} + else if ( (LA73_294==EOF) && (synpred44_FTS())) {s = 348;} + else if ( (LA73_294==RPAREN) && (synpred44_FTS())) {s = 349;} + else if ( (LA73_294==OR) && (synpred44_FTS())) {s = 350;} + else if ( (LA73_294==BAR) && (synpred44_FTS())) {s = 351;} + else if ( (LA73_294==EXCLAMATION) && (synpred44_FTS())) {s = 352;} + else if ( (LA73_294==AT) && (synpred44_FTS())) {s = 353;} + else if ( (LA73_294==FTSPHRASE) && (synpred44_FTS())) {s = 354;} + else if ( (LA73_294==LSQUARE) && (synpred44_FTS())) {s = 355;} + else if ( (LA73_294==LT) && (synpred44_FTS())) {s = 356;} + else if ( (LA73_294==COMMA||LA73_294==DOT) && (synpred44_FTS())) {s = 357;} + else if ( (LA73_294==EQUALS) && (synpred44_FTS())) {s = 358;} + else if ( (LA73_294==LPAREN) && (synpred44_FTS())) {s = 359;} + else if ( (LA73_294==PERCENT) && (synpred44_FTS())) {s = 360;} + else if ( (LA73_294==PLUS) && (synpred44_FTS())) {s = 361;} + else if ( (LA73_294==MINUS) && (synpred44_FTS())) {s = 362;} + + input.seek(index73_294); + if ( s>=0 ) return s; + break; + + case 148 : + int LA73_229 = input.LA(1); + + int index73_229 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_229==COMMA||LA73_229==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_229); + if ( s>=0 ) return s; + break; + + case 149 : + int LA73_365 = input.LA(1); + + int index73_365 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_365==DOT) ) {s = 426;} + else if ( (LA73_365==COMMA) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_365); + if ( s>=0 ) return s; + break; + + case 150 : + int LA73_369 = input.LA(1); + + int index73_369 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_369==COMMA||LA73_369==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_369); + if ( s>=0 ) return s; + break; + + case 151 : + int LA73_322 = input.LA(1); + + int index73_322 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_322==COMMA||LA73_322==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_322); + if ( s>=0 ) return s; + break; + + case 152 : + int LA73_332 = input.LA(1); + + int index73_332 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_332); + if ( s>=0 ) return s; + break; + + case 153 : + int LA73_227 = input.LA(1); + + int index73_227 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_227==COMMA||LA73_227==DOT) ) {s = 293;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_227); + if ( s>=0 ) return s; + break; + + case 154 : + int LA73_126 = input.LA(1); + + int index73_126 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_126==COMMA||LA73_126==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_126); + if ( s>=0 ) return s; + break; + + case 155 : + int LA73_129 = input.LA(1); + + int index73_129 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 210;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 212;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_129); + if ( s>=0 ) return s; + break; + + case 156 : + int LA73_440 = input.LA(1); + + int index73_440 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_440); + if ( s>=0 ) return s; + break; + + case 157 : + int LA73_454 = input.LA(1); + + int index73_454 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_454); + if ( s>=0 ) return s; + break; + + case 158 : + int LA73_144 = input.LA(1); + + int index73_144 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_144==COMMA||LA73_144==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_144); + if ( s>=0 ) return s; + break; + + case 159 : + int LA73_426 = input.LA(1); + + int index73_426 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_426==ID) ) {s = 451;} + else if ( (LA73_426==FTSWORD) ) {s = 415;} + else if ( (LA73_426==FTSPRE) ) {s = 416;} + else if ( (LA73_426==FTSWILD) ) {s = 417;} + else if ( (LA73_426==NOT) ) {s = 418;} + else if ( (LA73_426==TO) ) {s = 419;} + else if ( (LA73_426==DECIMAL_INTEGER_LITERAL) ) {s = 420;} + else if ( (LA73_426==FLOATING_POINT_LITERAL) ) {s = 421;} + else if ( (LA73_426==STAR) ) {s = 422;} + else if ( (LA73_426==QUESTION_MARK) ) {s = 423;} + else if ( (LA73_426==DATETIME) ) {s = 424;} + else if ( (LA73_426==URI) ) {s = 425;} + else if ( (LA73_426==TILDA) && (synpred44_FTS())) {s = 344;} + else if ( (LA73_426==CARAT) && (synpred44_FTS())) {s = 345;} + else if ( (LA73_426==AND) && (synpred44_FTS())) {s = 346;} + else if ( (LA73_426==AMP) && (synpred44_FTS())) {s = 347;} + else if ( (LA73_426==EOF) && (synpred44_FTS())) {s = 348;} + else if ( (LA73_426==RPAREN) && (synpred44_FTS())) {s = 349;} + else if ( (LA73_426==OR) && (synpred44_FTS())) {s = 350;} + else if ( (LA73_426==BAR) && (synpred44_FTS())) {s = 351;} + else if ( (LA73_426==EXCLAMATION) && (synpred44_FTS())) {s = 352;} + else if ( (LA73_426==AT) && (synpred44_FTS())) {s = 353;} + else if ( (LA73_426==FTSPHRASE) && (synpred44_FTS())) {s = 354;} + else if ( (LA73_426==LSQUARE) && (synpred44_FTS())) {s = 355;} + else if ( (LA73_426==LT) && (synpred44_FTS())) {s = 356;} + else if ( (LA73_426==COMMA||LA73_426==DOT) && (synpred44_FTS())) {s = 357;} + else if ( (LA73_426==EQUALS) && (synpred44_FTS())) {s = 358;} + else if ( (LA73_426==LPAREN) && (synpred44_FTS())) {s = 359;} + else if ( (LA73_426==PERCENT) && (synpred44_FTS())) {s = 360;} + else if ( (LA73_426==PLUS) && (synpred44_FTS())) {s = 361;} + else if ( (LA73_426==MINUS) && (synpred44_FTS())) {s = 362;} + + input.seek(index73_426); + if ( s>=0 ) return s; + break; + + case 160 : + int LA73_421 = input.LA(1); + + int index73_421 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_421); + if ( s>=0 ) return s; + break; + + case 161 : + int LA73_125 = input.LA(1); + + int index73_125 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_125==COMMA||LA73_125==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_125); + if ( s>=0 ) return s; + break; + + case 162 : + int LA73_432 = input.LA(1); + + int index73_432 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_432); + if ( s>=0 ) return s; + break; + + case 163 : + int LA73_412 = input.LA(1); + + int index73_412 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_412); + if ( s>=0 ) return s; + break; + + case 164 : + int LA73_446 = input.LA(1); + + int index73_446 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_446); + if ( s>=0 ) return s; + break; + + case 165 : + int LA73_231 = input.LA(1); + + int index73_231 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_231==COMMA||LA73_231==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_231); + if ( s>=0 ) return s; + break; + + case 166 : + int LA73_181 = input.LA(1); + + int index73_181 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_181==COMMA||LA73_181==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_181); + if ( s>=0 ) return s; + break; + + case 167 : + int LA73_185 = input.LA(1); + + int index73_185 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_185==COMMA||LA73_185==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_185); + if ( s>=0 ) return s; + break; + + case 168 : + int LA73_378 = input.LA(1); + + int index73_378 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_378); + if ( s>=0 ) return s; + break; + + case 169 : + int LA73_339 = input.LA(1); + + int index73_339 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_339); + if ( s>=0 ) return s; + break; + + case 170 : + int LA73_71 = input.LA(1); + + int index73_71 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_71==ID) ) {s = 111;} + else if ( (LA73_71==FTSWORD) ) {s = 112;} + else if ( (LA73_71==FTSPRE) ) {s = 113;} + else if ( (LA73_71==FTSWILD) ) {s = 114;} + else if ( (LA73_71==NOT) ) {s = 115;} + else if ( (LA73_71==TO) ) {s = 116;} + else if ( (LA73_71==DECIMAL_INTEGER_LITERAL) ) {s = 117;} + else if ( (LA73_71==FLOATING_POINT_LITERAL) ) {s = 118;} + else if ( (LA73_71==STAR) ) {s = 119;} + else if ( (LA73_71==QUESTION_MARK) ) {s = 120;} + else if ( (LA73_71==DATETIME) ) {s = 121;} + else if ( (LA73_71==URI) ) {s = 51;} + else if ( (LA73_71==TILDA) && (synpred56_FTS())) {s = 52;} + else if ( (LA73_71==CARAT) && (synpred56_FTS())) {s = 53;} + else if ( (LA73_71==AND) && (synpred56_FTS())) {s = 54;} + else if ( (LA73_71==AMP) && (synpred56_FTS())) {s = 55;} + else if ( (LA73_71==EOF) && (synpred56_FTS())) {s = 56;} + else if ( (LA73_71==RPAREN) && (synpred56_FTS())) {s = 57;} + else if ( (LA73_71==OR) && (synpred56_FTS())) {s = 58;} + else if ( (LA73_71==BAR) && (synpred56_FTS())) {s = 59;} + else if ( (LA73_71==EXCLAMATION) && (synpred56_FTS())) {s = 60;} + else if ( (LA73_71==AT) && (synpred56_FTS())) {s = 61;} + else if ( (LA73_71==FTSPHRASE) && (synpred56_FTS())) {s = 62;} + else if ( (LA73_71==LSQUARE) && (synpred56_FTS())) {s = 63;} + else if ( (LA73_71==LT) && (synpred56_FTS())) {s = 64;} + else if ( (LA73_71==COMMA||LA73_71==DOT) && (synpred56_FTS())) {s = 65;} + else if ( (LA73_71==EQUALS) && (synpred56_FTS())) {s = 66;} + else if ( (LA73_71==LPAREN) && (synpred56_FTS())) {s = 67;} + else if ( (LA73_71==PERCENT) && (synpred56_FTS())) {s = 68;} + else if ( (LA73_71==PLUS) && (synpred56_FTS())) {s = 69;} + else if ( (LA73_71==MINUS) && (synpred56_FTS())) {s = 70;} + + input.seek(index73_71); + if ( s>=0 ) return s; + break; + + case 171 : + int LA73_225 = input.LA(1); + + int index73_225 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_225==COMMA||LA73_225==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_225); + if ( s>=0 ) return s; + break; + + case 172 : + int LA73_315 = input.LA(1); + + int index73_315 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_315==COMMA||LA73_315==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_315); + if ( s>=0 ) return s; + break; + + case 173 : + int LA73_375 = input.LA(1); + + int index73_375 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_375); + if ( s>=0 ) return s; + break; + + case 174 : + int LA73_404 = input.LA(1); + + int index73_404 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_404==COMMA||LA73_404==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_404); + if ( s>=0 ) return s; + break; + + case 175 : + int LA73_260 = input.LA(1); + + int index73_260 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_260==ID) ) {s = 301;} + else if ( (LA73_260==FTSWORD) ) {s = 302;} + else if ( (LA73_260==FTSPRE) ) {s = 303;} + else if ( (LA73_260==FTSWILD) ) {s = 304;} + else if ( (LA73_260==NOT) ) {s = 305;} + else if ( (LA73_260==TO) ) {s = 306;} + else if ( (LA73_260==DECIMAL_INTEGER_LITERAL) ) {s = 307;} + else if ( (LA73_260==FLOATING_POINT_LITERAL) ) {s = 308;} + else if ( (LA73_260==STAR) ) {s = 309;} + else if ( (LA73_260==QUESTION_MARK) ) {s = 310;} + else if ( (LA73_260==DATETIME) ) {s = 311;} + else if ( (LA73_260==URI) ) {s = 312;} + else if ( (LA73_260==TILDA) && (synpred48_FTS())) {s = 240;} + else if ( (LA73_260==CARAT) && (synpred48_FTS())) {s = 241;} + else if ( (LA73_260==AND) && (synpred48_FTS())) {s = 242;} + else if ( (LA73_260==AMP) && (synpred48_FTS())) {s = 243;} + else if ( (LA73_260==EOF) && (synpred48_FTS())) {s = 244;} + else if ( (LA73_260==RPAREN) && (synpred48_FTS())) {s = 245;} + else if ( (LA73_260==OR) && (synpred48_FTS())) {s = 246;} + else if ( (LA73_260==BAR) && (synpred48_FTS())) {s = 247;} + else if ( (LA73_260==EXCLAMATION) && (synpred48_FTS())) {s = 248;} + else if ( (LA73_260==AT) && (synpred48_FTS())) {s = 249;} + else if ( (LA73_260==FTSPHRASE) && (synpred48_FTS())) {s = 250;} + else if ( (LA73_260==LSQUARE) && (synpred48_FTS())) {s = 251;} + else if ( (LA73_260==LT) && (synpred48_FTS())) {s = 252;} + else if ( (LA73_260==COMMA||LA73_260==DOT) && (synpred48_FTS())) {s = 253;} + else if ( (LA73_260==EQUALS) && (synpred48_FTS())) {s = 254;} + else if ( (LA73_260==LPAREN) && (synpred48_FTS())) {s = 255;} + else if ( (LA73_260==PERCENT) && (synpred48_FTS())) {s = 256;} + else if ( (LA73_260==PLUS) && (synpred48_FTS())) {s = 257;} + else if ( (LA73_260==MINUS) && (synpred48_FTS())) {s = 258;} + + input.seek(index73_260); + if ( s>=0 ) return s; + break; + + case 176 : + int LA73_323 = input.LA(1); + + int index73_323 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_323==COMMA||LA73_323==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_323); + if ( s>=0 ) return s; + break; + + case 177 : + int LA73_149 = input.LA(1); + + int index73_149 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_149==COMMA||LA73_149==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_149); + if ( s>=0 ) return s; + break; + + case 178 : + int LA73_230 = input.LA(1); + + int index73_230 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_230==COMMA||LA73_230==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_230); + if ( s>=0 ) return s; + break; + + case 179 : + int LA73_76 = input.LA(1); + + int index73_76 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_76==COMMA||LA73_76==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_76); + if ( s>=0 ) return s; + break; + + case 180 : + int LA73_133 = input.LA(1); + + int index73_133 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_133==COMMA||LA73_133==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_133); + if ( s>=0 ) return s; + break; + + case 181 : + int LA73_311 = input.LA(1); + + int index73_311 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_311==COMMA||LA73_311==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_311); + if ( s>=0 ) return s; + break; + + case 182 : + int LA73_146 = input.LA(1); + + int index73_146 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_146==COMMA||LA73_146==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_146); + if ( s>=0 ) return s; + break; + + case 183 : + int LA73_214 = input.LA(1); + + int index73_214 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_214==ID) ) {s = 228;} + else if ( (LA73_214==FTSWORD) ) {s = 229;} + else if ( (LA73_214==FTSPRE) ) {s = 230;} + else if ( (LA73_214==FTSWILD) ) {s = 231;} + else if ( (LA73_214==NOT) ) {s = 232;} + else if ( (LA73_214==TO) ) {s = 233;} + else if ( (LA73_214==DECIMAL_INTEGER_LITERAL) ) {s = 234;} + else if ( (LA73_214==FLOATING_POINT_LITERAL) ) {s = 235;} + else if ( (LA73_214==STAR) ) {s = 236;} + else if ( (LA73_214==QUESTION_MARK) ) {s = 237;} + else if ( (LA73_214==DATETIME) ) {s = 238;} + else if ( (LA73_214==URI) ) {s = 239;} + else if ( (LA73_214==TILDA) && (synpred48_FTS())) {s = 240;} + else if ( (LA73_214==CARAT) && (synpred48_FTS())) {s = 241;} + else if ( (LA73_214==AND) && (synpred48_FTS())) {s = 242;} + else if ( (LA73_214==AMP) && (synpred48_FTS())) {s = 243;} + else if ( (LA73_214==EOF) && (synpred48_FTS())) {s = 244;} + else if ( (LA73_214==RPAREN) && (synpred48_FTS())) {s = 245;} + else if ( (LA73_214==OR) && (synpred48_FTS())) {s = 246;} + else if ( (LA73_214==BAR) && (synpred48_FTS())) {s = 247;} + else if ( (LA73_214==EXCLAMATION) && (synpred48_FTS())) {s = 248;} + else if ( (LA73_214==AT) && (synpred48_FTS())) {s = 249;} + else if ( (LA73_214==FTSPHRASE) && (synpred48_FTS())) {s = 250;} + else if ( (LA73_214==LSQUARE) && (synpred48_FTS())) {s = 251;} + else if ( (LA73_214==LT) && (synpred48_FTS())) {s = 252;} + else if ( (LA73_214==COMMA||LA73_214==DOT) && (synpred48_FTS())) {s = 253;} + else if ( (LA73_214==EQUALS) && (synpred48_FTS())) {s = 254;} + else if ( (LA73_214==LPAREN) && (synpred48_FTS())) {s = 255;} + else if ( (LA73_214==PERCENT) && (synpred48_FTS())) {s = 256;} + else if ( (LA73_214==PLUS) && (synpred48_FTS())) {s = 257;} + else if ( (LA73_214==MINUS) && (synpred48_FTS())) {s = 258;} + + input.seek(index73_214); + if ( s>=0 ) return s; + break; + + case 184 : + int LA73_208 = input.LA(1); + + int index73_208 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_208==ID) ) {s = 227;} + else if ( (LA73_208==FTSWORD) ) {s = 178;} + else if ( (LA73_208==FTSPRE) ) {s = 179;} + else if ( (LA73_208==FTSWILD) ) {s = 180;} + else if ( (LA73_208==NOT) ) {s = 181;} + else if ( (LA73_208==TO) ) {s = 182;} + else if ( (LA73_208==DECIMAL_INTEGER_LITERAL) ) {s = 183;} + else if ( (LA73_208==FLOATING_POINT_LITERAL) ) {s = 184;} + else if ( (LA73_208==STAR) ) {s = 185;} + else if ( (LA73_208==QUESTION_MARK) ) {s = 186;} + else if ( (LA73_208==DATETIME) ) {s = 187;} + else if ( (LA73_208==URI) ) {s = 188;} + else if ( (LA73_208==TILDA) && (synpred51_FTS())) {s = 189;} + else if ( (LA73_208==CARAT) && (synpred51_FTS())) {s = 190;} + else if ( (LA73_208==AND) && (synpred51_FTS())) {s = 191;} + else if ( (LA73_208==AMP) && (synpred51_FTS())) {s = 192;} + else if ( (LA73_208==EOF) && (synpred51_FTS())) {s = 193;} + else if ( (LA73_208==RPAREN) && (synpred51_FTS())) {s = 194;} + else if ( (LA73_208==OR) && (synpred51_FTS())) {s = 195;} + else if ( (LA73_208==BAR) && (synpred51_FTS())) {s = 196;} + else if ( (LA73_208==EXCLAMATION) && (synpred51_FTS())) {s = 197;} + else if ( (LA73_208==AT) && (synpred51_FTS())) {s = 198;} + else if ( (LA73_208==FTSPHRASE) && (synpred51_FTS())) {s = 199;} + else if ( (LA73_208==LSQUARE) && (synpred51_FTS())) {s = 200;} + else if ( (LA73_208==LT) && (synpred51_FTS())) {s = 201;} + else if ( (LA73_208==COMMA||LA73_208==DOT) && (synpred51_FTS())) {s = 202;} + else if ( (LA73_208==EQUALS) && (synpred51_FTS())) {s = 203;} + else if ( (LA73_208==LPAREN) && (synpred51_FTS())) {s = 204;} + else if ( (LA73_208==PERCENT) && (synpred51_FTS())) {s = 205;} + else if ( (LA73_208==PLUS) && (synpred51_FTS())) {s = 206;} + else if ( (LA73_208==MINUS) && (synpred51_FTS())) {s = 207;} + + input.seek(index73_208); + if ( s>=0 ) return s; + break; + + case 185 : + int LA73_302 = input.LA(1); + + int index73_302 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_302==COMMA||LA73_302==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_302); + if ( s>=0 ) return s; + break; + + case 186 : + int LA73_455 = input.LA(1); + + int index73_455 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_455); + if ( s>=0 ) return s; + break; + + case 187 : + int LA73_441 = input.LA(1); + + int index73_441 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_441); + if ( s>=0 ) return s; + break; + + case 188 : + int LA73_363 = input.LA(1); + + int index73_363 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_363==ID) ) {s = 413;} + else if ( (LA73_363==FTSWORD) ) {s = 333;} + else if ( (LA73_363==FTSPRE) ) {s = 334;} + else if ( (LA73_363==FTSWILD) ) {s = 335;} + else if ( (LA73_363==NOT) ) {s = 336;} + else if ( (LA73_363==TO) ) {s = 337;} + else if ( (LA73_363==DECIMAL_INTEGER_LITERAL) ) {s = 338;} + else if ( (LA73_363==FLOATING_POINT_LITERAL) ) {s = 339;} + else if ( (LA73_363==STAR) ) {s = 340;} + else if ( (LA73_363==QUESTION_MARK) ) {s = 341;} + else if ( (LA73_363==DATETIME) ) {s = 342;} + else if ( (LA73_363==URI) ) {s = 343;} + else if ( (LA73_363==TILDA) && (synpred44_FTS())) {s = 344;} + else if ( (LA73_363==CARAT) && (synpred44_FTS())) {s = 345;} + else if ( (LA73_363==AND) && (synpred44_FTS())) {s = 346;} + else if ( (LA73_363==AMP) && (synpred44_FTS())) {s = 347;} + else if ( (LA73_363==EOF) && (synpred44_FTS())) {s = 348;} + else if ( (LA73_363==RPAREN) && (synpred44_FTS())) {s = 349;} + else if ( (LA73_363==OR) && (synpred44_FTS())) {s = 350;} + else if ( (LA73_363==BAR) && (synpred44_FTS())) {s = 351;} + else if ( (LA73_363==EXCLAMATION) && (synpred44_FTS())) {s = 352;} + else if ( (LA73_363==AT) && (synpred44_FTS())) {s = 353;} + else if ( (LA73_363==FTSPHRASE) && (synpred44_FTS())) {s = 354;} + else if ( (LA73_363==LSQUARE) && (synpred44_FTS())) {s = 355;} + else if ( (LA73_363==LT) && (synpred44_FTS())) {s = 356;} + else if ( (LA73_363==COMMA||LA73_363==DOT) && (synpred44_FTS())) {s = 357;} + else if ( (LA73_363==EQUALS) && (synpred44_FTS())) {s = 358;} + else if ( (LA73_363==LPAREN) && (synpred44_FTS())) {s = 359;} + else if ( (LA73_363==PERCENT) && (synpred44_FTS())) {s = 360;} + else if ( (LA73_363==PLUS) && (synpred44_FTS())) {s = 361;} + else if ( (LA73_363==MINUS) && (synpred44_FTS())) {s = 362;} + + input.seek(index73_363); + if ( s>=0 ) return s; + break; + + case 189 : + int LA73_427 = input.LA(1); + + int index73_427 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_427); + if ( s>=0 ) return s; + break; + + case 190 : + int LA73_402 = input.LA(1); + + int index73_402 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_402==ID) ) {s = 433;} + else if ( (LA73_402==FTSWORD) ) {s = 434;} + else if ( (LA73_402==FTSPRE) ) {s = 435;} + else if ( (LA73_402==FTSWILD) ) {s = 436;} + else if ( (LA73_402==NOT) ) {s = 437;} + else if ( (LA73_402==TO) ) {s = 438;} + else if ( (LA73_402==DECIMAL_INTEGER_LITERAL) ) {s = 439;} + else if ( (LA73_402==FLOATING_POINT_LITERAL) ) {s = 440;} + else if ( (LA73_402==STAR) ) {s = 441;} + else if ( (LA73_402==QUESTION_MARK) ) {s = 442;} + else if ( (LA73_402==DATETIME) ) {s = 443;} + else if ( (LA73_402==URI) ) {s = 444;} + else if ( (LA73_402==TILDA) && (synpred43_FTS())) {s = 382;} + else if ( (LA73_402==CARAT) && (synpred43_FTS())) {s = 383;} + else if ( (LA73_402==AND) && (synpred43_FTS())) {s = 384;} + else if ( (LA73_402==AMP) && (synpred43_FTS())) {s = 385;} + else if ( (LA73_402==EOF) && (synpred43_FTS())) {s = 386;} + else if ( (LA73_402==RPAREN) && (synpred43_FTS())) {s = 387;} + else if ( (LA73_402==OR) && (synpred43_FTS())) {s = 388;} + else if ( (LA73_402==BAR) && (synpred43_FTS())) {s = 389;} + else if ( (LA73_402==EXCLAMATION) && (synpred43_FTS())) {s = 390;} + else if ( (LA73_402==AT) && (synpred43_FTS())) {s = 391;} + else if ( (LA73_402==FTSPHRASE) && (synpred43_FTS())) {s = 392;} + else if ( (LA73_402==LSQUARE) && (synpred43_FTS())) {s = 393;} + else if ( (LA73_402==LT) && (synpred43_FTS())) {s = 394;} + else if ( (LA73_402==COMMA||LA73_402==DOT) && (synpred43_FTS())) {s = 395;} + else if ( (LA73_402==EQUALS) && (synpred43_FTS())) {s = 396;} + else if ( (LA73_402==LPAREN) && (synpred43_FTS())) {s = 397;} + else if ( (LA73_402==PERCENT) && (synpred43_FTS())) {s = 398;} + else if ( (LA73_402==PLUS) && (synpred43_FTS())) {s = 399;} + else if ( (LA73_402==MINUS) && (synpred43_FTS())) {s = 400;} + + input.seek(index73_402); + if ( s>=0 ) return s; + break; + + case 191 : + int LA73_340 = input.LA(1); + + int index73_340 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_340); + if ( s>=0 ) return s; + break; + + case 192 : + int LA73_422 = input.LA(1); + + int index73_422 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_422); + if ( s>=0 ) return s; + break; + + case 193 : + int LA73_443 = input.LA(1); + + int index73_443 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_443); + if ( s>=0 ) return s; + break; + + case 194 : + int LA73_337 = input.LA(1); + + int index73_337 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_337); + if ( s>=0 ) return s; + break; + + case 195 : + int LA73_177 = input.LA(1); + + int index73_177 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_177==COMMA||LA73_177==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_177); + if ( s>=0 ) return s; + break; + + case 196 : + int LA73_265 = input.LA(1); + + int index73_265 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_265==COMMA||LA73_265==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_265); + if ( s>=0 ) return s; + break; + + case 197 : + int LA73_232 = input.LA(1); + + int index73_232 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_232==COMMA||LA73_232==DOT) ) {s = 294;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_232); + if ( s>=0 ) return s; + break; + + case 198 : + int LA73_442 = input.LA(1); + + int index73_442 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_442); + if ( s>=0 ) return s; + break; + + case 199 : + int LA73_226 = input.LA(1); + + int index73_226 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_226==COMMA||LA73_226==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_226); + if ( s>=0 ) return s; + break; + + case 200 : + int LA73_316 = input.LA(1); + + int index73_316 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_316==COMMA||LA73_316==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_316); + if ( s>=0 ) return s; + break; + + case 201 : + int LA73_456 = input.LA(1); + + int index73_456 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_456); + if ( s>=0 ) return s; + break; + + case 202 : + int LA73_303 = input.LA(1); + + int index73_303 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_303==COMMA||LA73_303==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_303); + if ( s>=0 ) return s; + break; + + case 203 : + int LA73_405 = input.LA(1); + + int index73_405 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_405==COMMA||LA73_405==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_405); + if ( s>=0 ) return s; + break; + + case 204 : + int LA73_127 = input.LA(1); + + int index73_127 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_127==COMMA||LA73_127==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_127); + if ( s>=0 ) return s; + break; + + case 205 : + int LA73_147 = input.LA(1); + + int index73_147 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_147==COMMA||LA73_147==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_147); + if ( s>=0 ) return s; + break; + + case 206 : + int LA73_419 = input.LA(1); + + int index73_419 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_419); + if ( s>=0 ) return s; + break; + + case 207 : + int LA73_314 = input.LA(1); + + int index73_314 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_314==DOT) ) {s = 401;} + else if ( (LA73_314==COMMA) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_314); + if ( s>=0 ) return s; + break; + + case 208 : + int LA73_103 = input.LA(1); + + int index73_103 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_103==ID) ) {s = 129;} + else if ( (LA73_103==FTSWORD) ) {s = 130;} + else if ( (LA73_103==FTSPRE) ) {s = 131;} + else if ( (LA73_103==FTSWILD) ) {s = 132;} + else if ( (LA73_103==NOT) ) {s = 133;} + else if ( (LA73_103==TO) ) {s = 134;} + else if ( (LA73_103==DECIMAL_INTEGER_LITERAL) ) {s = 135;} + else if ( (LA73_103==FLOATING_POINT_LITERAL) ) {s = 136;} + else if ( (LA73_103==STAR) ) {s = 137;} + else if ( (LA73_103==QUESTION_MARK) ) {s = 138;} + else if ( (LA73_103==DATETIME) ) {s = 139;} + else if ( (LA73_103==URI) ) {s = 83;} + else if ( (LA73_103==TILDA) && (synpred55_FTS())) {s = 84;} + else if ( (LA73_103==CARAT) && (synpred55_FTS())) {s = 85;} + else if ( (LA73_103==AND) && (synpred55_FTS())) {s = 86;} + else if ( (LA73_103==AMP) && (synpred55_FTS())) {s = 87;} + else if ( (LA73_103==EOF) && (synpred55_FTS())) {s = 88;} + else if ( (LA73_103==RPAREN) && (synpred55_FTS())) {s = 89;} + else if ( (LA73_103==OR) && (synpred55_FTS())) {s = 90;} + else if ( (LA73_103==BAR) && (synpred55_FTS())) {s = 91;} + else if ( (LA73_103==EXCLAMATION) && (synpred55_FTS())) {s = 92;} + else if ( (LA73_103==AT) && (synpred55_FTS())) {s = 93;} + else if ( (LA73_103==FTSPHRASE) && (synpred55_FTS())) {s = 94;} + else if ( (LA73_103==LSQUARE) && (synpred55_FTS())) {s = 95;} + else if ( (LA73_103==LT) && (synpred55_FTS())) {s = 96;} + else if ( (LA73_103==COMMA||LA73_103==DOT) && (synpred55_FTS())) {s = 97;} + else if ( (LA73_103==EQUALS) && (synpred55_FTS())) {s = 98;} + else if ( (LA73_103==LPAREN) && (synpred55_FTS())) {s = 99;} + else if ( (LA73_103==PERCENT) && (synpred55_FTS())) {s = 100;} + else if ( (LA73_103==PLUS) && (synpred55_FTS())) {s = 101;} + else if ( (LA73_103==MINUS) && (synpred55_FTS())) {s = 102;} + + input.seek(index73_103); + if ( s>=0 ) return s; + break; + + case 209 : + int LA73_447 = input.LA(1); + + int index73_447 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_447); + if ( s>=0 ) return s; + break; + + case 210 : + int LA73_457 = input.LA(1); + + int index73_457 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_457); + if ( s>=0 ) return s; + break; + + case 211 : + int LA73_293 = input.LA(1); + + int index73_293 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_293==ID) ) {s = 320;} + else if ( (LA73_293==FTSWORD) ) {s = 321;} + else if ( (LA73_293==FTSPRE) ) {s = 322;} + else if ( (LA73_293==FTSWILD) ) {s = 323;} + else if ( (LA73_293==NOT) ) {s = 324;} + else if ( (LA73_293==TO) ) {s = 325;} + else if ( (LA73_293==DECIMAL_INTEGER_LITERAL) ) {s = 326;} + else if ( (LA73_293==FLOATING_POINT_LITERAL) ) {s = 327;} + else if ( (LA73_293==STAR) ) {s = 328;} + else if ( (LA73_293==QUESTION_MARK) ) {s = 329;} + else if ( (LA73_293==DATETIME) ) {s = 330;} + else if ( (LA73_293==URI) ) {s = 331;} + else if ( (LA73_293==TILDA) && (synpred47_FTS())) {s = 273;} + else if ( (LA73_293==CARAT) && (synpred47_FTS())) {s = 274;} + else if ( (LA73_293==AND) && (synpred47_FTS())) {s = 275;} + else if ( (LA73_293==AMP) && (synpred47_FTS())) {s = 276;} + else if ( (LA73_293==EOF) && (synpred47_FTS())) {s = 277;} + else if ( (LA73_293==RPAREN) && (synpred47_FTS())) {s = 278;} + else if ( (LA73_293==OR) && (synpred47_FTS())) {s = 279;} + else if ( (LA73_293==BAR) && (synpred47_FTS())) {s = 280;} + else if ( (LA73_293==EXCLAMATION) && (synpred47_FTS())) {s = 281;} + else if ( (LA73_293==AT) && (synpred47_FTS())) {s = 282;} + else if ( (LA73_293==FTSPHRASE) && (synpred47_FTS())) {s = 283;} + else if ( (LA73_293==LSQUARE) && (synpred47_FTS())) {s = 284;} + else if ( (LA73_293==LT) && (synpred47_FTS())) {s = 285;} + else if ( (LA73_293==COMMA||LA73_293==DOT) && (synpred47_FTS())) {s = 286;} + else if ( (LA73_293==EQUALS) && (synpred47_FTS())) {s = 287;} + else if ( (LA73_293==LPAREN) && (synpred47_FTS())) {s = 288;} + else if ( (LA73_293==PERCENT) && (synpred47_FTS())) {s = 289;} + else if ( (LA73_293==PLUS) && (synpred47_FTS())) {s = 290;} + else if ( (LA73_293==MINUS) && (synpred47_FTS())) {s = 291;} + + input.seek(index73_293); + if ( s>=0 ) return s; + break; + + case 212 : + int LA73_319 = input.LA(1); + + int index73_319 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_319==COMMA||LA73_319==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_319); + if ( s>=0 ) return s; + break; + + case 213 : + int LA73_413 = input.LA(1); + + int index73_413 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_413); + if ( s>=0 ) return s; + break; + + case 214 : + int LA73_222 = input.LA(1); + + int index73_222 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_222==DOT) ) {s = 292;} + else if ( (LA73_222==COMMA) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_222); + if ( s>=0 ) return s; + break; + + case 215 : + int LA73_305 = input.LA(1); + + int index73_305 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_305==COMMA||LA73_305==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_305); + if ( s>=0 ) return s; + break; + + case 216 : + int LA73_220 = input.LA(1); + + int index73_220 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_220==COMMA||LA73_220==DOT) ) {s = 260;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_220); + if ( s>=0 ) return s; + break; + + case 217 : + int LA73_259 = input.LA(1); + + int index73_259 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_259==ID) ) {s = 300;} + else if ( (LA73_259==FTSWORD) ) {s = 229;} + else if ( (LA73_259==FTSPRE) ) {s = 230;} + else if ( (LA73_259==FTSWILD) ) {s = 231;} + else if ( (LA73_259==NOT) ) {s = 232;} + else if ( (LA73_259==TO) ) {s = 233;} + else if ( (LA73_259==DECIMAL_INTEGER_LITERAL) ) {s = 234;} + else if ( (LA73_259==FLOATING_POINT_LITERAL) ) {s = 235;} + else if ( (LA73_259==STAR) ) {s = 236;} + else if ( (LA73_259==QUESTION_MARK) ) {s = 237;} + else if ( (LA73_259==DATETIME) ) {s = 238;} + else if ( (LA73_259==URI) ) {s = 239;} + else if ( (LA73_259==TILDA) && (synpred48_FTS())) {s = 240;} + else if ( (LA73_259==CARAT) && (synpred48_FTS())) {s = 241;} + else if ( (LA73_259==AND) && (synpred48_FTS())) {s = 242;} + else if ( (LA73_259==AMP) && (synpred48_FTS())) {s = 243;} + else if ( (LA73_259==EOF) && (synpred48_FTS())) {s = 244;} + else if ( (LA73_259==RPAREN) && (synpred48_FTS())) {s = 245;} + else if ( (LA73_259==OR) && (synpred48_FTS())) {s = 246;} + else if ( (LA73_259==BAR) && (synpred48_FTS())) {s = 247;} + else if ( (LA73_259==EXCLAMATION) && (synpred48_FTS())) {s = 248;} + else if ( (LA73_259==AT) && (synpred48_FTS())) {s = 249;} + else if ( (LA73_259==FTSPHRASE) && (synpred48_FTS())) {s = 250;} + else if ( (LA73_259==LSQUARE) && (synpred48_FTS())) {s = 251;} + else if ( (LA73_259==LT) && (synpred48_FTS())) {s = 252;} + else if ( (LA73_259==COMMA||LA73_259==DOT) && (synpred48_FTS())) {s = 253;} + else if ( (LA73_259==EQUALS) && (synpred48_FTS())) {s = 254;} + else if ( (LA73_259==LPAREN) && (synpred48_FTS())) {s = 255;} + else if ( (LA73_259==PERCENT) && (synpred48_FTS())) {s = 256;} + else if ( (LA73_259==PLUS) && (synpred48_FTS())) {s = 257;} + else if ( (LA73_259==MINUS) && (synpred48_FTS())) {s = 258;} + + input.seek(index73_259); + if ( s>=0 ) return s; + break; + + case 218 : + int LA73_371 = input.LA(1); + + int index73_371 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_371); + if ( s>=0 ) return s; + break; + + case 219 : + int LA73_326 = input.LA(1); + + int index73_326 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_326==COMMA||LA73_326==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_326); + if ( s>=0 ) return s; + break; + + case 220 : + int LA73_423 = input.LA(1); + + int index73_423 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_423); + if ( s>=0 ) return s; + break; + + case 221 : + int LA73_261 = input.LA(1); + + int index73_261 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_261==COMMA||LA73_261==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_261); + if ( s>=0 ) return s; + break; + + case 222 : + int LA73_341 = input.LA(1); + + int index73_341 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_341); + if ( s>=0 ) return s; + break; + + case 223 : + int LA73_403 = input.LA(1); + + int index73_403 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_403==DOT) ) {s = 445;} + else if ( (LA73_403==COMMA) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_403); + if ( s>=0 ) return s; + break; + + case 224 : + int LA73_182 = input.LA(1); + + int index73_182 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_182==COMMA||LA73_182==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_182); + if ( s>=0 ) return s; + break; + + case 225 : + int LA73_406 = input.LA(1); + + int index73_406 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_406==COMMA||LA73_406==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_406); + if ( s>=0 ) return s; + break; + + case 226 : + int LA73_434 = input.LA(1); + + int index73_434 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_434); + if ( s>=0 ) return s; + break; + + case 227 : + int LA73_304 = input.LA(1); + + int index73_304 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_304==COMMA||LA73_304==DOT) ) {s = 364;} + else if ( (synpred46_FTS()) ) {s = 174;} + else if ( (synpred48_FTS()) ) {s = 258;} + + input.seek(index73_304); + if ( s>=0 ) return s; + break; + + case 228 : + int LA73_379 = input.LA(1); + + int index73_379 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_379); + if ( s>=0 ) return s; + break; + + case 229 : + int LA73_187 = input.LA(1); + + int index73_187 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_187==COMMA||LA73_187==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_187); + if ( s>=0 ) return s; + break; + + case 230 : + int LA73_267 = input.LA(1); + + int index73_267 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_267==COMMA||LA73_267==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_267); + if ( s>=0 ) return s; + break; + + case 231 : + int LA73_317 = input.LA(1); + + int index73_317 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_317==COMMA||LA73_317==DOT) ) {s = 313;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_317); + if ( s>=0 ) return s; + break; + + case 232 : + int LA73_445 = input.LA(1); + + int index73_445 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_445==ID) ) {s = 457;} + else if ( (LA73_445==FTSWORD) ) {s = 434;} + else if ( (LA73_445==FTSPRE) ) {s = 435;} + else if ( (LA73_445==FTSWILD) ) {s = 436;} + else if ( (LA73_445==NOT) ) {s = 437;} + else if ( (LA73_445==TO) ) {s = 438;} + else if ( (LA73_445==DECIMAL_INTEGER_LITERAL) ) {s = 439;} + else if ( (LA73_445==FLOATING_POINT_LITERAL) ) {s = 440;} + else if ( (LA73_445==STAR) ) {s = 441;} + else if ( (LA73_445==QUESTION_MARK) ) {s = 442;} + else if ( (LA73_445==DATETIME) ) {s = 443;} + else if ( (LA73_445==URI) ) {s = 444;} + else if ( (LA73_445==TILDA) && (synpred43_FTS())) {s = 382;} + else if ( (LA73_445==CARAT) && (synpred43_FTS())) {s = 383;} + else if ( (LA73_445==AND) && (synpred43_FTS())) {s = 384;} + else if ( (LA73_445==AMP) && (synpred43_FTS())) {s = 385;} + else if ( (LA73_445==EOF) && (synpred43_FTS())) {s = 386;} + else if ( (LA73_445==RPAREN) && (synpred43_FTS())) {s = 387;} + else if ( (LA73_445==OR) && (synpred43_FTS())) {s = 388;} + else if ( (LA73_445==BAR) && (synpred43_FTS())) {s = 389;} + else if ( (LA73_445==EXCLAMATION) && (synpred43_FTS())) {s = 390;} + else if ( (LA73_445==AT) && (synpred43_FTS())) {s = 391;} + else if ( (LA73_445==FTSPHRASE) && (synpred43_FTS())) {s = 392;} + else if ( (LA73_445==LSQUARE) && (synpred43_FTS())) {s = 393;} + else if ( (LA73_445==LT) && (synpred43_FTS())) {s = 394;} + else if ( (LA73_445==COMMA||LA73_445==DOT) && (synpred43_FTS())) {s = 395;} + else if ( (LA73_445==EQUALS) && (synpred43_FTS())) {s = 396;} + else if ( (LA73_445==LPAREN) && (synpred43_FTS())) {s = 397;} + else if ( (LA73_445==PERCENT) && (synpred43_FTS())) {s = 398;} + else if ( (LA73_445==PLUS) && (synpred43_FTS())) {s = 399;} + else if ( (LA73_445==MINUS) && (synpred43_FTS())) {s = 400;} + + input.seek(index73_445); + if ( s>=0 ) return s; + break; + + case 233 : + int LA73_50 = input.LA(1); + + int index73_50 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_50==COMMA||LA73_50==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_50); + if ( s>=0 ) return s; + break; + + case 234 : + int LA73_121 = input.LA(1); + + int index73_121 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_121==COMMA||LA73_121==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_121); + if ( s>=0 ) return s; + break; + + case 235 : + int LA73_216 = input.LA(1); + + int index73_216 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_216==COMMA||LA73_216==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_216); + if ( s>=0 ) return s; + break; + + case 236 : + int LA73_380 = input.LA(1); + + int index73_380 = input.index(); + input.rewind(); + s = -1; + if ( (synpred41_FTS()) ) {s = 209;} + else if ( (synpred43_FTS()) ) {s = 400;} + + input.seek(index73_380); + if ( s>=0 ) return s; + break; + + case 237 : + int LA73_148 = input.LA(1); + + int index73_148 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_148==COMMA||LA73_148==DOT) ) {s = 214;} + else if ( (synpred50_FTS()) ) {s = 176;} + else if ( (synpred52_FTS()) ) {s = 170;} + + input.seek(index73_148); + if ( s>=0 ) return s; + break; + + case 238 : + int LA73_77 = input.LA(1); + + int index73_77 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_77==COMMA||LA73_77==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_77); + if ( s>=0 ) return s; + break; + + case 239 : + int LA73_134 = input.LA(1); + + int index73_134 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_134==COMMA||LA73_134==DOT) ) {s = 122;} + else if ( (synpred53_FTS()) ) {s = 123;} + else if ( (synpred55_FTS()) ) {s = 102;} + else if ( (true) ) {s = 34;} + + input.seek(index73_134); + if ( s>=0 ) return s; + break; + + case 240 : + int LA73_324 = input.LA(1); + + int index73_324 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_324==COMMA||LA73_324==DOT) ) {s = 402;} + else if ( (synpred45_FTS()) ) {s = 211;} + else if ( (synpred47_FTS()) ) {s = 291;} + + input.seek(index73_324); + if ( s>=0 ) return s; + break; + + case 241 : + int LA73_178 = input.LA(1); + + int index73_178 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_178==COMMA||LA73_178==DOT) ) {s = 221;} + else if ( (synpred49_FTS()) ) {s = 213;} + else if ( (synpred51_FTS()) ) {s = 207;} + + input.seek(index73_178); + if ( s>=0 ) return s; + break; + + case 242 : + int LA73_448 = input.LA(1); + + int index73_448 = input.index(); + input.rewind(); + s = -1; + if ( (synpred42_FTS()) ) {s = 172;} + else if ( (synpred44_FTS()) ) {s = 362;} + + input.seek(index73_448); + if ( s>=0 ) return s; + break; + + case 243 : + int LA73_108 = input.LA(1); + + int index73_108 = input.index(); + input.rewind(); + s = -1; + if ( (LA73_108==COMMA||LA73_108==DOT) ) {s = 104;} + else if ( (synpred54_FTS()) ) {s = 105;} + else if ( (synpred56_FTS()) ) {s = 70;} + else if ( (true) ) {s = 27;} + + input.seek(index73_108); + if ( s>=0 ) return s; + break; + } + if (state.backtracking>0) {state.failed=true; return -1;} + NoViableAltException nvae = + new NoViableAltException(getDescription(), 73, _s, input); + error(nvae); + throw nvae; + } + } + + public static final BitSet FOLLOW_ftsDisjunction_in_ftsQuery577 = new BitSet(new long[]{0x0000000000000000L}); + public static final BitSet FOLLOW_EOF_in_ftsQuery579 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_cmisExplicitDisjunction_in_ftsDisjunction639 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsExplicitDisjunction_in_ftsDisjunction653 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsImplicitDisjunction_in_ftsDisjunction667 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsImplicitConjunction_in_ftsExplicitDisjunction700 = new BitSet(new long[]{0x0000000000000082L,0x0000000000020000L}); + public static final BitSet FOLLOW_or_in_ftsExplicitDisjunction703 = new BitSet(new long[]{0x803C80000920A8F0L,0x0000016101164138L}); + public static final BitSet FOLLOW_ftsImplicitConjunction_in_ftsExplicitDisjunction705 = new BitSet(new long[]{0x0000000000000082L,0x0000000000020000L}); + public static final BitSet FOLLOW_cmisConjunction_in_cmisExplicitDisjunction789 = new BitSet(new long[]{0x0000000000000082L,0x0000000000020000L}); + public static final BitSet FOLLOW_or_in_cmisExplicitDisjunction792 = new BitSet(new long[]{0x803C80000020A800L,0x0000014101004100L}); + public static final BitSet FOLLOW_cmisConjunction_in_cmisExplicitDisjunction794 = new BitSet(new long[]{0x0000000000000082L,0x0000000000020000L}); + public static final BitSet FOLLOW_or_in_ftsImplicitDisjunction879 = new BitSet(new long[]{0x803C80000920A8E0L,0x0000016101164138L}); + public static final BitSet FOLLOW_ftsExplicitConjunction_in_ftsImplicitDisjunction882 = new BitSet(new long[]{0x803C80000920A8E2L,0x0000016101164138L}); + public static final BitSet FOLLOW_ftsPrefixed_in_ftsExplicitConjunction969 = new BitSet(new long[]{0x0000000000000032L}); + public static final BitSet FOLLOW_and_in_ftsExplicitConjunction972 = new BitSet(new long[]{0x803C80000920A8E0L,0x0000016101164138L}); + public static final BitSet FOLLOW_ftsPrefixed_in_ftsExplicitConjunction974 = new BitSet(new long[]{0x0000000000000032L}); + public static final BitSet FOLLOW_and_in_ftsImplicitConjunction1059 = new BitSet(new long[]{0x803C80000920A8E0L,0x0000016101164138L}); + public static final BitSet FOLLOW_ftsPrefixed_in_ftsImplicitConjunction1062 = new BitSet(new long[]{0x803C80000920A8F2L,0x0000016101164138L}); + public static final BitSet FOLLOW_cmisPrefixed_in_cmisConjunction1146 = new BitSet(new long[]{0x803C80000020A802L,0x0000014101004100L}); + public static final BitSet FOLLOW_not_in_ftsPrefixed1238 = new BitSet(new long[]{0x803C80000120A860L,0x0000016101064038L}); + public static final BitSet FOLLOW_ftsTest_in_ftsPrefixed1240 = new BitSet(new long[]{0x0000000000000202L}); + public static final BitSet FOLLOW_boost_in_ftsPrefixed1242 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsTest_in_ftsPrefixed1306 = new BitSet(new long[]{0x0000000000000202L}); + public static final BitSet FOLLOW_boost_in_ftsPrefixed1308 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_PLUS_in_ftsPrefixed1372 = new BitSet(new long[]{0x803C80000120A860L,0x0000016101064038L}); + public static final BitSet FOLLOW_ftsTest_in_ftsPrefixed1374 = new BitSet(new long[]{0x0000000000000202L}); + public static final BitSet FOLLOW_boost_in_ftsPrefixed1376 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_BAR_in_ftsPrefixed1440 = new BitSet(new long[]{0x803C80000120A860L,0x0000016101064038L}); + public static final BitSet FOLLOW_ftsTest_in_ftsPrefixed1442 = new BitSet(new long[]{0x0000000000000202L}); + public static final BitSet FOLLOW_boost_in_ftsPrefixed1444 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_MINUS_in_ftsPrefixed1508 = new BitSet(new long[]{0x803C80000120A860L,0x0000016101064038L}); + public static final BitSet FOLLOW_ftsTest_in_ftsPrefixed1510 = new BitSet(new long[]{0x0000000000000202L}); + public static final BitSet FOLLOW_boost_in_ftsPrefixed1512 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_cmisTest_in_cmisPrefixed1597 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_MINUS_in_cmisPrefixed1657 = new BitSet(new long[]{0x803C80000020A800L,0x0000014101004000L}); + public static final BitSet FOLLOW_cmisTest_in_cmisPrefixed1659 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupProximity_in_ftsTest1751 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsRange_in_ftsTest1828 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroup_in_ftsTest1907 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsTermOrPhrase_in_ftsTest1956 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsExactTermOrPhrase_in_ftsTest1985 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsTokenisedTermOrPhrase_in_ftsTest2015 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LPAREN_in_ftsTest2046 = new BitSet(new long[]{0x803C80000920A8F0L,0x0000016101164138L}); + public static final BitSet FOLLOW_ftsDisjunction_in_ftsTest2048 = new BitSet(new long[]{0x0000000000000000L,0x0000000008000000L}); + public static final BitSet FOLLOW_RPAREN_in_ftsTest2050 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_template_in_ftsTest2083 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_cmisTerm_in_cmisTest2136 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_cmisPhrase_in_cmisTest2196 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_PERCENT_in_template2277 = new BitSet(new long[]{0x8000000000000060L,0x0000014000024000L}); + public static final BitSet FOLLOW_tempReference_in_template2279 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_PERCENT_in_template2339 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000008L}); + public static final BitSet FOLLOW_LPAREN_in_template2341 = new BitSet(new long[]{0x8000000000000060L,0x0000014000024000L}); + public static final BitSet FOLLOW_tempReference_in_template2344 = new BitSet(new long[]{0x8000000000000860L,0x0000014008024000L}); + public static final BitSet FOLLOW_COMMA_in_template2346 = new BitSet(new long[]{0x8000000000000060L,0x0000014008024000L}); + public static final BitSet FOLLOW_RPAREN_in_template2351 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_TILDA_in_fuzzy2433 = new BitSet(new long[]{0x0000800000008000L}); + public static final BitSet FOLLOW_number_in_fuzzy2435 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_TILDA_in_slop2516 = new BitSet(new long[]{0x0000000000008000L}); + public static final BitSet FOLLOW_DECIMAL_INTEGER_LITERAL_in_slop2518 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_CARAT_in_boost2599 = new BitSet(new long[]{0x0000800000008000L}); + public static final BitSet FOLLOW_number_in_boost2601 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fieldReference_in_ftsTermOrPhrase2690 = new BitSet(new long[]{0x0000000000000400L}); + public static final BitSet FOLLOW_COLON_in_ftsTermOrPhrase2692 = new BitSet(new long[]{0x803C80000020A800L,0x0000014101004000L}); + public static final BitSet FOLLOW_FTSPHRASE_in_ftsTermOrPhrase2720 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_slop_in_ftsTermOrPhrase2728 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWord_in_ftsTermOrPhrase2795 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_fuzzy_in_ftsTermOrPhrase2804 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSPHRASE_in_ftsTermOrPhrase2865 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_slop_in_ftsTermOrPhrase2873 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWord_in_ftsTermOrPhrase2923 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_fuzzy_in_ftsTermOrPhrase2932 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_EQUALS_in_ftsExactTermOrPhrase3011 = new BitSet(new long[]{0x803C80000020A860L,0x0000014101024000L}); + public static final BitSet FOLLOW_fieldReference_in_ftsExactTermOrPhrase3039 = new BitSet(new long[]{0x0000000000000400L}); + public static final BitSet FOLLOW_COLON_in_ftsExactTermOrPhrase3041 = new BitSet(new long[]{0x803C80000020A800L,0x0000014101004000L}); + public static final BitSet FOLLOW_FTSPHRASE_in_ftsExactTermOrPhrase3069 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_slop_in_ftsExactTermOrPhrase3077 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWord_in_ftsExactTermOrPhrase3144 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_fuzzy_in_ftsExactTermOrPhrase3153 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSPHRASE_in_ftsExactTermOrPhrase3214 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_slop_in_ftsExactTermOrPhrase3222 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWord_in_ftsExactTermOrPhrase3272 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_fuzzy_in_ftsExactTermOrPhrase3281 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_TILDA_in_ftsTokenisedTermOrPhrase3362 = new BitSet(new long[]{0x803C80000020A860L,0x0000014101024000L}); + public static final BitSet FOLLOW_fieldReference_in_ftsTokenisedTermOrPhrase3390 = new BitSet(new long[]{0x0000000000000400L}); + public static final BitSet FOLLOW_COLON_in_ftsTokenisedTermOrPhrase3392 = new BitSet(new long[]{0x803C80000020A800L,0x0000014101004000L}); + public static final BitSet FOLLOW_FTSPHRASE_in_ftsTokenisedTermOrPhrase3420 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_slop_in_ftsTokenisedTermOrPhrase3428 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWord_in_ftsTokenisedTermOrPhrase3495 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_fuzzy_in_ftsTokenisedTermOrPhrase3504 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSPHRASE_in_ftsTokenisedTermOrPhrase3565 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_slop_in_ftsTokenisedTermOrPhrase3573 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWord_in_ftsTokenisedTermOrPhrase3623 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_fuzzy_in_ftsTokenisedTermOrPhrase3632 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWord_in_cmisTerm3705 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSPHRASE_in_cmisPhrase3759 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fieldReference_in_ftsRange3814 = new BitSet(new long[]{0x0000000000000400L}); + public static final BitSet FOLLOW_COLON_in_ftsRange3816 = new BitSet(new long[]{0x803C80000000A000L,0x0000010100000030L}); + public static final BitSet FOLLOW_ftsFieldGroupRange_in_ftsRange3820 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fieldReference_in_ftsFieldGroup3876 = new BitSet(new long[]{0x0000000000000400L}); + public static final BitSet FOLLOW_COLON_in_ftsFieldGroup3878 = new BitSet(new long[]{0x0000000000000000L,0x0000000000000008L}); + public static final BitSet FOLLOW_LPAREN_in_ftsFieldGroup3880 = new BitSet(new long[]{0x803C80000920A8B0L,0x0000016101124138L}); + public static final BitSet FOLLOW_ftsFieldGroupDisjunction_in_ftsFieldGroup3882 = new BitSet(new long[]{0x0000000000000000L,0x0000000008000000L}); + public static final BitSet FOLLOW_RPAREN_in_ftsFieldGroup3884 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupExplicitDisjunction_in_ftsFieldGroupDisjunction3969 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupImplicitDisjunction_in_ftsFieldGroupDisjunction3983 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupImplicitConjunction_in_ftsFieldGroupExplicitDisjunction4016 = new BitSet(new long[]{0x0000000000000082L,0x0000000000020000L}); + public static final BitSet FOLLOW_or_in_ftsFieldGroupExplicitDisjunction4019 = new BitSet(new long[]{0x803C80000920A8B0L,0x0000016101104138L}); + public static final BitSet FOLLOW_ftsFieldGroupImplicitConjunction_in_ftsFieldGroupExplicitDisjunction4021 = new BitSet(new long[]{0x0000000000000082L,0x0000000000020000L}); + public static final BitSet FOLLOW_or_in_ftsFieldGroupImplicitDisjunction4106 = new BitSet(new long[]{0x803C80000920A880L,0x0000016101104138L}); + public static final BitSet FOLLOW_ftsFieldGroupExplicitConjunction_in_ftsFieldGroupImplicitDisjunction4109 = new BitSet(new long[]{0x803C80000920A882L,0x0000016101124138L}); + public static final BitSet FOLLOW_ftsFieldGroupPrefixed_in_ftsFieldGroupExplicitConjunction4196 = new BitSet(new long[]{0x0000000000000032L}); + public static final BitSet FOLLOW_and_in_ftsFieldGroupExplicitConjunction4199 = new BitSet(new long[]{0x803C80000920A880L,0x0000016101104138L}); + public static final BitSet FOLLOW_ftsFieldGroupPrefixed_in_ftsFieldGroupExplicitConjunction4201 = new BitSet(new long[]{0x0000000000000032L}); + public static final BitSet FOLLOW_and_in_ftsFieldGroupImplicitConjunction4286 = new BitSet(new long[]{0x803C80000920A880L,0x0000016101104138L}); + public static final BitSet FOLLOW_ftsFieldGroupPrefixed_in_ftsFieldGroupImplicitConjunction4289 = new BitSet(new long[]{0x803C80000920A8B2L,0x0000016101104138L}); + public static final BitSet FOLLOW_not_in_ftsFieldGroupPrefixed4379 = new BitSet(new long[]{0x803C80000120A800L,0x0000016101004038L}); + public static final BitSet FOLLOW_ftsFieldGroupTest_in_ftsFieldGroupPrefixed4381 = new BitSet(new long[]{0x0000000000000202L}); + public static final BitSet FOLLOW_boost_in_ftsFieldGroupPrefixed4383 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupTest_in_ftsFieldGroupPrefixed4447 = new BitSet(new long[]{0x0000000000000202L}); + public static final BitSet FOLLOW_boost_in_ftsFieldGroupPrefixed4449 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_PLUS_in_ftsFieldGroupPrefixed4513 = new BitSet(new long[]{0x803C80000120A800L,0x0000016101004038L}); + public static final BitSet FOLLOW_ftsFieldGroupTest_in_ftsFieldGroupPrefixed4515 = new BitSet(new long[]{0x0000000000000202L}); + public static final BitSet FOLLOW_boost_in_ftsFieldGroupPrefixed4517 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_BAR_in_ftsFieldGroupPrefixed4581 = new BitSet(new long[]{0x803C80000120A800L,0x0000016101004038L}); + public static final BitSet FOLLOW_ftsFieldGroupTest_in_ftsFieldGroupPrefixed4583 = new BitSet(new long[]{0x0000000000000202L}); + public static final BitSet FOLLOW_boost_in_ftsFieldGroupPrefixed4585 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_MINUS_in_ftsFieldGroupPrefixed4649 = new BitSet(new long[]{0x803C80000120A800L,0x0000016101004038L}); + public static final BitSet FOLLOW_ftsFieldGroupTest_in_ftsFieldGroupPrefixed4651 = new BitSet(new long[]{0x0000000000000202L}); + public static final BitSet FOLLOW_boost_in_ftsFieldGroupPrefixed4653 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupProximity_in_ftsFieldGroupTest4744 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupTerm_in_ftsFieldGroupTest4810 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_fuzzy_in_ftsFieldGroupTest4820 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupExactTerm_in_ftsFieldGroupTest4891 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_fuzzy_in_ftsFieldGroupTest4901 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupPhrase_in_ftsFieldGroupTest4972 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_slop_in_ftsFieldGroupTest4982 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupExactPhrase_in_ftsFieldGroupTest5053 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_slop_in_ftsFieldGroupTest5063 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupTokenisedPhrase_in_ftsFieldGroupTest5134 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_slop_in_ftsFieldGroupTest5144 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupSynonym_in_ftsFieldGroupTest5215 = new BitSet(new long[]{0x0000000000000002L,0x0000002000000000L}); + public static final BitSet FOLLOW_fuzzy_in_ftsFieldGroupTest5225 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupRange_in_ftsFieldGroupTest5296 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LPAREN_in_ftsFieldGroupTest5356 = new BitSet(new long[]{0x803C80000920A8B0L,0x0000016101124138L}); + public static final BitSet FOLLOW_ftsFieldGroupDisjunction_in_ftsFieldGroupTest5358 = new BitSet(new long[]{0x0000000000000000L,0x0000000008000000L}); + public static final BitSet FOLLOW_RPAREN_in_ftsFieldGroupTest5360 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWord_in_ftsFieldGroupTerm5413 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_EQUALS_in_ftsFieldGroupExactTerm5446 = new BitSet(new long[]{0x803880000020A800L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsFieldGroupTerm_in_ftsFieldGroupExactTerm5448 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSPHRASE_in_ftsFieldGroupPhrase5501 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_EQUALS_in_ftsFieldGroupExactPhrase5542 = new BitSet(new long[]{0x0000000001000000L}); + public static final BitSet FOLLOW_ftsFieldGroupExactPhrase_in_ftsFieldGroupExactPhrase5544 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_TILDA_in_ftsFieldGroupTokenisedPhrase5605 = new BitSet(new long[]{0x0000000001000000L}); + public static final BitSet FOLLOW_ftsFieldGroupExactPhrase_in_ftsFieldGroupTokenisedPhrase5607 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_TILDA_in_ftsFieldGroupSynonym5660 = new BitSet(new long[]{0x803880000020A800L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsFieldGroupTerm_in_ftsFieldGroupSynonym5662 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupProximityTerm_in_ftsFieldGroupProximity5715 = new BitSet(new long[]{0x0000000000000000L,0x0000000100000000L}); + public static final BitSet FOLLOW_proximityGroup_in_ftsFieldGroupProximity5725 = new BitSet(new long[]{0x803880000000A000L,0x0000014100004000L}); + public static final BitSet FOLLOW_ftsFieldGroupProximityTerm_in_ftsFieldGroupProximity5727 = new BitSet(new long[]{0x0000000000000002L,0x0000000100000000L}); + public static final BitSet FOLLOW_ID_in_ftsFieldGroupProximityTerm5791 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSWORD_in_ftsFieldGroupProximityTerm5803 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSPRE_in_ftsFieldGroupProximityTerm5815 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSWILD_in_ftsFieldGroupProximityTerm5827 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_NOT_in_ftsFieldGroupProximityTerm5839 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_TO_in_ftsFieldGroupProximityTerm5851 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_DECIMAL_INTEGER_LITERAL_in_ftsFieldGroupProximityTerm5863 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FLOATING_POINT_LITERAL_in_ftsFieldGroupProximityTerm5875 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_DATETIME_in_ftsFieldGroupProximityTerm5887 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_STAR_in_ftsFieldGroupProximityTerm5899 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_URI_in_ftsFieldGroupProximityTerm5911 = new BitSet(new long[]{0x8000000000000020L,0x0000004000024000L}); + public static final BitSet FOLLOW_identifier_in_ftsFieldGroupProximityTerm5913 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_STAR_in_proximityGroup5946 = new BitSet(new long[]{0x0000000000000002L,0x0000000000000008L}); + public static final BitSet FOLLOW_LPAREN_in_proximityGroup5949 = new BitSet(new long[]{0x0000000000008000L,0x0000000008000000L}); + public static final BitSet FOLLOW_DECIMAL_INTEGER_LITERAL_in_proximityGroup5951 = new BitSet(new long[]{0x0000000000000000L,0x0000000008000000L}); + public static final BitSet FOLLOW_RPAREN_in_proximityGroup5954 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsRangeWord_in_ftsFieldGroupRange6038 = new BitSet(new long[]{0x0000000000400000L}); + public static final BitSet FOLLOW_DOTDOT_in_ftsFieldGroupRange6040 = new BitSet(new long[]{0x803C80000000A000L,0x0000010100000000L}); + public static final BitSet FOLLOW_ftsRangeWord_in_ftsFieldGroupRange6042 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_range_left_in_ftsFieldGroupRange6080 = new BitSet(new long[]{0x803C80000000A000L,0x0000010100000000L}); + public static final BitSet FOLLOW_ftsRangeWord_in_ftsFieldGroupRange6082 = new BitSet(new long[]{0x0000000000000000L,0x0000004000000000L}); + public static final BitSet FOLLOW_TO_in_ftsFieldGroupRange6084 = new BitSet(new long[]{0x803C80000000A000L,0x0000010100000000L}); + public static final BitSet FOLLOW_ftsRangeWord_in_ftsFieldGroupRange6086 = new BitSet(new long[]{0x2000000000000000L,0x0000000010000000L}); + public static final BitSet FOLLOW_range_right_in_ftsFieldGroupRange6088 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LSQUARE_in_range_left6147 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_LT_in_range_left6179 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_RSQUARE_in_range_right6232 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_GT_in_range_right6264 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_AT_in_fieldReference6320 = new BitSet(new long[]{0x8000000000000020L,0x0000014000024000L}); + public static final BitSet FOLLOW_prefix_in_fieldReference6357 = new BitSet(new long[]{0x8000000000000020L,0x0000004000024000L}); + public static final BitSet FOLLOW_uri_in_fieldReference6377 = new BitSet(new long[]{0x8000000000000020L,0x0000004000024000L}); + public static final BitSet FOLLOW_identifier_in_fieldReference6398 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_AT_in_tempReference6485 = new BitSet(new long[]{0x8000000000000020L,0x0000014000024000L}); + public static final BitSet FOLLOW_prefix_in_tempReference6514 = new BitSet(new long[]{0x8000000000000020L,0x0000004000024000L}); + public static final BitSet FOLLOW_uri_in_tempReference6534 = new BitSet(new long[]{0x8000000000000020L,0x0000004000024000L}); + public static final BitSet FOLLOW_identifier_in_tempReference6555 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_identifier_in_prefix6642 = new BitSet(new long[]{0x0000000000000400L}); + public static final BitSet FOLLOW_COLON_in_prefix6644 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_URI_in_uri6725 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ID_in_identifier6827 = new BitSet(new long[]{0x0000000000200000L}); + public static final BitSet FOLLOW_DOT_in_identifier6829 = new BitSet(new long[]{0x8000000000000000L}); + public static final BitSet FOLLOW_ID_in_identifier6833 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ID_in_identifier6882 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_TO_in_identifier6949 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_OR_in_identifier6987 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_AND_in_identifier7025 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_NOT_in_identifier7064 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_ftsWord7182 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7188 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7190 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7196 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7198 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7204 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7206 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7212 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7214 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7220 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7280 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7282 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7288 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7290 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7296 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7298 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7304 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7306 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7312 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_ftsWord7379 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7385 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7387 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7393 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7395 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7401 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7403 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7409 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7411 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7475 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7477 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7483 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7485 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7491 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7493 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7499 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7501 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_ftsWord7566 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7572 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7574 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7580 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7582 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7588 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7590 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7596 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7650 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7652 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7658 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7660 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7666 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7668 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7674 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_ftsWord7732 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7738 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7740 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7746 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7748 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7754 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7756 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7812 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7814 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7820 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7822 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7828 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7830 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_ftsWord7886 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7892 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7894 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7900 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7902 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7908 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7954 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7956 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7962 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord7964 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord7970 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_ftsWord8021 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord8027 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord8029 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord8035 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord8037 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord8086 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord8088 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord8094 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord8096 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_ftsWord8145 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord8151 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord8153 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord8159 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord8197 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord8199 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord8205 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_ftsWord8247 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord8253 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord8255 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord8295 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_ftsWord8297 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_ftsWord8313 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord8319 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_ftsWord8332 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ID_in_ftsWordBase8377 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSWORD_in_ftsWordBase8389 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSPRE_in_ftsWordBase8401 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSWILD_in_ftsWordBase8414 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_NOT_in_ftsWordBase8427 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_TO_in_ftsWordBase8439 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_DECIMAL_INTEGER_LITERAL_in_ftsWordBase8451 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FLOATING_POINT_LITERAL_in_ftsWordBase8463 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_STAR_in_ftsWordBase8475 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_QUESTION_MARK_in_ftsWordBase8487 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_DATETIME_in_ftsWordBase8499 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_URI_in_ftsWordBase8511 = new BitSet(new long[]{0x8000000000000020L,0x0000004000024000L}); + public static final BitSet FOLLOW_identifier_in_ftsWordBase8513 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ID_in_ftsRangeWord8593 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSWORD_in_ftsRangeWord8605 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSPRE_in_ftsRangeWord8617 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSWILD_in_ftsRangeWord8629 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FTSPHRASE_in_ftsRangeWord8641 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_DECIMAL_INTEGER_LITERAL_in_ftsRangeWord8653 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_FLOATING_POINT_LITERAL_in_ftsRangeWord8665 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_DATETIME_in_ftsRangeWord8677 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_STAR_in_ftsRangeWord8689 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_URI_in_ftsRangeWord8701 = new BitSet(new long[]{0x8000000000000020L,0x0000004000024000L}); + public static final BitSet FOLLOW_identifier_in_ftsRangeWord8703 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_OR_in_or8738 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_BAR_in_or8750 = new BitSet(new long[]{0x0000000000000080L}); + public static final BitSet FOLLOW_BAR_in_or8752 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_AND_in_and8785 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_AMP_in_and8797 = new BitSet(new long[]{0x0000000000000010L}); + public static final BitSet FOLLOW_AMP_in_and8799 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_not_in_synpred1_FTS1233 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupProximity_in_synpred2_FTS1746 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsRange_in_synpred3_FTS1823 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroup_in_synpred4_FTS1902 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsTermOrPhrase_in_synpred5_FTS1951 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsExactTermOrPhrase_in_synpred6_FTS1980 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsTokenisedTermOrPhrase_in_synpred7_FTS2010 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fieldReference_in_synpred8_FTS2683 = new BitSet(new long[]{0x0000000000000400L}); + public static final BitSet FOLLOW_COLON_in_synpred8_FTS2685 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_slop_in_synpred9_FTS2724 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fuzzy_in_synpred10_FTS2799 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_slop_in_synpred11_FTS2869 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fuzzy_in_synpred12_FTS2927 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fieldReference_in_synpred13_FTS3032 = new BitSet(new long[]{0x0000000000000400L}); + public static final BitSet FOLLOW_COLON_in_synpred13_FTS3034 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_slop_in_synpred14_FTS3073 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fuzzy_in_synpred15_FTS3148 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_slop_in_synpred16_FTS3218 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fuzzy_in_synpred17_FTS3276 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fieldReference_in_synpred18_FTS3383 = new BitSet(new long[]{0x0000000000000400L}); + public static final BitSet FOLLOW_COLON_in_synpred18_FTS3385 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_slop_in_synpred19_FTS3424 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fuzzy_in_synpred20_FTS3499 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_slop_in_synpred21_FTS3569 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fuzzy_in_synpred22_FTS3627 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_not_in_synpred23_FTS4374 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupProximity_in_synpred24_FTS4739 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupTerm_in_synpred25_FTS4805 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fuzzy_in_synpred26_FTS4815 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupExactTerm_in_synpred27_FTS4886 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fuzzy_in_synpred28_FTS4896 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupPhrase_in_synpred29_FTS4967 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_slop_in_synpred30_FTS4977 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupExactPhrase_in_synpred31_FTS5048 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_slop_in_synpred32_FTS5058 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupTokenisedPhrase_in_synpred33_FTS5129 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_slop_in_synpred34_FTS5139 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupSynonym_in_synpred35_FTS5210 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_fuzzy_in_synpred36_FTS5220 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsFieldGroupRange_in_synpred37_FTS5291 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_proximityGroup_in_synpred38_FTS5720 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_prefix_in_synpred39_FTS6352 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ID_in_synpred40_FTS6807 = new BitSet(new long[]{0x0000000000200000L}); + public static final BitSet FOLLOW_DOT_in_synpred40_FTS6809 = new BitSet(new long[]{0x8000000000000000L}); + public static final BitSet FOLLOW_ID_in_synpred40_FTS6811 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_synpred41_FTS7127 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred41_FTS7133 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred41_FTS7135 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred41_FTS7141 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred41_FTS7143 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred41_FTS7149 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred41_FTS7151 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred41_FTS7157 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred41_FTS7159 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred41_FTS7165 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred42_FTS7233 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred42_FTS7235 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred42_FTS7241 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred42_FTS7243 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred42_FTS7249 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred42_FTS7251 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred42_FTS7257 = new BitSet(new long[]{0x0000000000200000L}); + public static final BitSet FOLLOW_DOT_in_synpred42_FTS7259 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_COMMA_in_synpred42_FTS7261 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred42_FTS7263 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_synpred43_FTS7326 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred43_FTS7332 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred43_FTS7334 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred43_FTS7340 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred43_FTS7342 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred43_FTS7348 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred43_FTS7350 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred43_FTS7356 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred43_FTS7358 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred44_FTS7428 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred44_FTS7430 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred44_FTS7436 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred44_FTS7438 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred44_FTS7444 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred44_FTS7446 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred44_FTS7452 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred44_FTS7454 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_synpred45_FTS7519 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred45_FTS7525 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred45_FTS7527 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred45_FTS7533 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred45_FTS7535 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred45_FTS7541 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred45_FTS7543 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred45_FTS7549 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred46_FTS7609 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred46_FTS7611 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred46_FTS7617 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred46_FTS7619 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred46_FTS7625 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred46_FTS7627 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred46_FTS7633 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_synpred47_FTS7687 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred47_FTS7693 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred47_FTS7695 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred47_FTS7701 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred47_FTS7703 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred47_FTS7709 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred47_FTS7711 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred48_FTS7773 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred48_FTS7775 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred48_FTS7781 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred48_FTS7783 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred48_FTS7789 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred48_FTS7791 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_synpred49_FTS7847 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred49_FTS7853 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred49_FTS7855 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred49_FTS7861 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred49_FTS7863 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred49_FTS7869 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred50_FTS7921 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred50_FTS7923 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred50_FTS7929 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred50_FTS7931 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred50_FTS7937 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_synpred51_FTS7984 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred51_FTS7990 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred51_FTS7992 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred51_FTS7998 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred51_FTS8000 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred52_FTS8054 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred52_FTS8056 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred52_FTS8062 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred52_FTS8064 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_synpred53_FTS8114 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred53_FTS8120 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred53_FTS8122 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred53_FTS8128 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred54_FTS8172 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred54_FTS8174 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred54_FTS8180 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_set_in_synpred55_FTS8218 = new BitSet(new long[]{0x803880000000A000L,0x0000014101004000L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred55_FTS8224 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred55_FTS8226 = new BitSet(new long[]{0x0000000000000002L}); + public static final BitSet FOLLOW_ftsWordBase_in_synpred56_FTS8272 = new BitSet(new long[]{0x0000000000200800L}); + public static final BitSet FOLLOW_set_in_synpred56_FTS8274 = new BitSet(new long[]{0x0000000000000002L}); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTSQueryException.java b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTSQueryException.java new file mode 100644 index 0000000000..898f08669c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTSQueryException.java @@ -0,0 +1,62 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.parsers; + +import org.alfresco.error.AlfrescoRuntimeException; + +public class FTSQueryException extends AlfrescoRuntimeException +{ + + /** + * + */ + private static final long serialVersionUID = -4554441051084471802L; + + public FTSQueryException(String msgId, Object[] msgParams, Throwable cause) + { + super(msgId, msgParams, cause); + // TODO Auto-generated constructor stub + } + + public FTSQueryException(String msgId, Object[] msgParams) + { + super(msgId, msgParams); + // TODO Auto-generated constructor stub + } + + public FTSQueryException(String msgId, Throwable cause) + { + super(msgId, cause); + // TODO Auto-generated constructor stub + } + + public FTSQueryException(String msgId) + { + super(msgId); + // TODO Auto-generated constructor stub + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTSQueryParser.java b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTSQueryParser.java new file mode 100644 index 0000000000..7fe89e44f1 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/FTSQueryParser.java @@ -0,0 +1,1686 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.parsers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.search.adaptor.lucene.AnalysisMode; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.Column; +import org.alfresco.repo.search.impl.querymodel.Constraint; +import org.alfresco.repo.search.impl.querymodel.Constraint.Occur; +import org.alfresco.repo.search.impl.querymodel.Function; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.LiteralArgument; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.QueryModelFactory; +import org.alfresco.repo.search.impl.querymodel.QueryOptions.Connective; +import org.alfresco.repo.search.impl.querymodel.Selector; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSFuzzyTerm; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSPhrase; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSPrefixTerm; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSProximity; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSRange; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSTerm; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSWildTerm; +import org.alfresco.repo.search.impl.querymodel.impl.functions.PropertyAccessor; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.util.ISO9075; +import org.antlr.runtime.ANTLRStringStream; +import org.antlr.runtime.CharStream; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.Token; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +public class FTSQueryParser +{ + public static enum RerankPhase + { + SINGLE_PASS, SINGLE_PASS_WITH_AUTO_PHRASE, QUERY_PHASE, RERANK_PHASE; + } + + private static TestNodeBuilder testNodeBuilder = new TestNodeBuilder(); + + public static void setTestNodeBuilder(TestNodeBuilder tnb) + { + testNodeBuilder = tnb; + } + + static final String KEY_REPLACELONESTAR = "KEY_REPLACELONESTAR"; + static final String VALUE_REPLACELONESTAR = "ISNODE:T"; + + @SuppressWarnings("unused") + static public Constraint buildFTS(String ftsExpression, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, Selector selector, + Map columnMap, FTSParser.Mode mode, Connective defaultFieldConnective, Map templates, String defaultField, RerankPhase rerankPhase) + { + // TODO: Decode sql escape for '' should do in CMIS layer + + // parse templates to trees ... + + Map templateTrees = new HashMap(); + + if (templates == null) + { + templates = new HashMap(); + } + templates.put(KEY_REPLACELONESTAR, VALUE_REPLACELONESTAR); + + for (String name : templates.keySet()) + { + FTSParser parser = null; + + try + { + String templateDefinition = templates.get(name); + CharStream cs = new ANTLRStringStream(templateDefinition); + FTSLexer lexer = new FTSLexer(cs); + CommonTokenStream tokens = new CommonTokenStream(lexer); + parser = new FTSParser(tokens); + parser.setMode(mode); + parser.setDefaultFieldConjunction(defaultFieldConnective == Connective.AND ? true : false); + CommonTree ftsNode = (CommonTree) parser.ftsQuery().getTree(); + //Check for duplicate template of properties e.g. NAME, name and NaMe. + if (templateTrees.containsKey(name.toLowerCase())) + { + throw new FTSQueryException("Duplicate template of property: " + name); + } + + templateTrees.put(name.toLowerCase(), ftsNode); + } + catch (RecognitionException e) + { + if (parser != null) + { + String[] tokenNames = parser.getTokenNames(); + String hdr = parser.getErrorHeader(e); + String msg = parser.getErrorMessage(e, tokenNames); + throw new FTSQueryException(hdr + "\n" + msg, e); + } + return null; + } + } + + FTSParser parser = null; + try + { + CharStream cs = new ANTLRStringStream(ftsExpression); + FTSLexer lexer = new FTSLexer(cs); + CommonTokenStream tokens = new CommonTokenStream(lexer); + parser = new FTSParser(tokens); + parser.setMode(mode); + parser.setDefaultFieldConjunction(defaultFieldConnective == Connective.AND ? true : false); + CommonTree ftsNode = (CommonTree) parser.ftsQuery().getTree(); + // Rewrite for auto phrase + if(rerankPhase != RerankPhase.RERANK_PHASE.SINGLE_PASS) + { + ftsNode = autoPhraseReWrite(ftsNode, defaultFieldConnective == Connective.AND ? true : false, rerankPhase); + } + return buildFTSConnective(null, ftsNode, factory, functionEvaluationContext, selector, columnMap, templateTrees, defaultField); + } + catch (RecognitionException e) + { + if (parser != null) + { + String[] tokenNames = parser.getTokenNames(); + String hdr = parser.getErrorHeader(e); + String msg = parser.getErrorMessage(e, tokenNames); + throw new FTSQueryException(hdr + "\n" + msg, e); + } + return null; + } + + } + + private static CommonTree autoPhraseReWrite(CommonTree node, boolean defaultConjunction, RerankPhase rerankPhase) { + if(node == null) + { + return node; + } + CommonTree newNode = new CommonTree(node); + if(isAutoPhrasable(node, defaultConjunction)) + { + StringBuilder phrase = new StringBuilder(); + LinkedList autoPhrased = new LinkedList(); + for (Object current : node.getChildren()) + { + CommonTree child = (CommonTree)current; + if((child.getType() == FTSParser.MANDATORY) || (child.getType() == FTSParser.DEFAULT)) + { + if(child.getChildCount() > 0) + { + CommonTree term = (CommonTree)child.getChild(0); + if((term.getType() == FTSParser.TERM) && (term.getChildCount() == 1)) + { + String termText = getText((List) term.getChildren()); + if(phrase.length() > 0) + { + phrase.append(" "); + } + phrase.append(termText); + autoPhrased.add(child); + } + else + { + CommonTree newChild = autoPhraseReWrite(child, defaultConjunction, rerankPhase); + newNode.addChild(newChild); + } + + } + } + else + { + CommonTree newChild = autoPhraseReWrite(child, defaultConjunction, rerankPhase); + newNode.addChild(newChild); + } + } + CommonTree disjunction = new CommonTree(new DisjunctionToken()); + newNode.addChild(disjunction); + + if(rerankPhase == RerankPhase.SINGLE_PASS_WITH_AUTO_PHRASE) + { + CommonTree termConjuctionLink = new CommonTree(new DefaultToken()); + disjunction.addChild(termConjuctionLink); + CommonTree termConjunction = new CommonTree(new ConjunctionToken()); + termConjuctionLink.addChild(termConjunction); + for(CommonTree phrased : autoPhrased) + { + CommonTree newPhrased = autoPhraseReWrite(phrased, defaultConjunction, rerankPhase); + termConjunction.addChild(newPhrased); + } + } + + + CommonTree phraseLink = new CommonTree(new DefaultToken()); + disjunction.addChild(phraseLink); + CommonTree phraseTree = new CommonTree(new PhraseToken()); + phraseLink.addChild(phraseTree); + phraseTree.addChild(new CommonTree(new WordToken(phrase.toString()))); + + } + else + { + if(node.getChildren() != null) + { + for (Object current : node.getChildren()) + { + CommonTree child = (CommonTree) current; + CommonTree newChild = autoPhraseReWrite(child, defaultConjunction, rerankPhase); + newNode.addChild(newChild); + } + } + } + return newNode; + } + + private static boolean isAutoPhrasable(CommonTree node, boolean defaultConjunction) { + if((node.getType() == FTSParser.CONJUNCTION) && (node.getChildCount() > 1)) + { + int simpleTermCount = 0; + for (Object current : node.getChildren()) + { + CommonTree child = (CommonTree) current; + if((child.getType() == FTSParser.MANDATORY) || (child.getType() == FTSParser.DEFAULT)) + { + if(child.getChildCount() > 0) + { + CommonTree item = (CommonTree)child.getChild(0); + if((item.getType() == FTSParser.TERM) && (item.getChildCount() == 1)) + { + simpleTermCount++; + } + } + } + else + { + return false; + } + } + return simpleTermCount > 1; + } + + return false; + + } + + static private Constraint buildFTSConnective(CommonTree fieldReferenceNode, CommonTree node, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap, Map templateTrees, String defaultField) + { + Connective connective; + switch (node.getType()) + { + case FTSParser.DISJUNCTION: + case FTSParser.FIELD_DISJUNCTION: + connective = Connective.OR; + break; + case FTSParser.CONJUNCTION: + case FTSParser.FIELD_CONJUNCTION: + connective = Connective.AND; + break; + default: + throw new FTSQueryException("Invalid connective ..." + node.getText()); + } + + List constraints = new ArrayList(node.getChildCount()); + CommonTree testNode; + for (int i = 0; i < node.getChildCount(); i++) + { + CommonTree subNode = (CommonTree) node.getChild(i); + Constraint constraint; + switch (subNode.getType()) + { + case FTSParser.DISJUNCTION: + case FTSParser.FIELD_DISJUNCTION: + case FTSParser.CONJUNCTION: + case FTSParser.FIELD_CONJUNCTION: + constraint = buildFTSConnective(fieldReferenceNode, subNode, factory, functionEvaluationContext, selector, columnMap, templateTrees, defaultField); + setBoost(constraint, subNode); + break; + case FTSParser.NEGATION: + case FTSParser.FIELD_NEGATION: + testNode = (CommonTree) subNode.getChild(0); + constraint = buildFTSTest(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap, templateTrees, defaultField); + constraint.setOccur(Occur.EXCLUDE); + setBoost(constraint, subNode); + break; + case FTSParser.DEFAULT: + case FTSParser.FIELD_DEFAULT: + testNode = (CommonTree) subNode.getChild(0); + constraint = buildFTSTest(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap, templateTrees, defaultField); + constraint.setOccur(Occur.DEFAULT); + setBoost(constraint, subNode); + break; + case FTSParser.MANDATORY: + case FTSParser.FIELD_MANDATORY: + testNode = (CommonTree) subNode.getChild(0); + constraint = buildFTSTest(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap, templateTrees, defaultField); + constraint.setOccur(Occur.MANDATORY); + setBoost(constraint, subNode); + break; + case FTSParser.OPTIONAL: + case FTSParser.FIELD_OPTIONAL: + testNode = (CommonTree) subNode.getChild(0); + constraint = buildFTSTest(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap, templateTrees, defaultField); + constraint.setOccur(Occur.OPTIONAL); + setBoost(constraint, subNode); + break; + case FTSParser.EXCLUDE: + case FTSParser.FIELD_EXCLUDE: + testNode = (CommonTree) subNode.getChild(0); + constraint = buildFTSTest(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap, templateTrees, defaultField); + constraint.setOccur(Occur.EXCLUDE); + setBoost(constraint, subNode); + break; + + default: + throw new FTSQueryException("Unsupported FTS option " + subNode.getText()); + } + constraints.add(constraint); + } + if (constraints.size() == 1 && Occur.EXCLUDE != constraints.get(0).getOccur()) + { + return constraints.get(0); + } + else + { + if (connective == Connective.OR) + { + return factory.createDisjunction(constraints); + } + else + { + return factory.createConjunction(constraints); + } + } + } + + static private void setBoost(Constraint constraint, CommonTree subNode) + { + for (int i = 0, l = subNode.getChildCount(); i < l; i++) + { + CommonTree child = (CommonTree) subNode.getChild(i); + if (child.getType() == FTSParser.BOOST) + { + String boostString = child.getChild(0).getText(); + float boost = Float.parseFloat(boostString); + constraint.setBoost(boost); + return; + } + } + } + + protected static class TestNodeBuilder + { + protected CommonTree build(CommonTree fieldReferenceNode, CommonTree argNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap, Map templateTrees, String defaultField) + { + CommonTree testNode = argNode; + // Check for template replacement + + PropertyArgument parg = null; + if (fieldReferenceNode != null) + { + parg = buildFieldReference("", fieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + } + else + { + CommonTree specifiedFieldReferenceNode = findFieldReference(testNode); + if (specifiedFieldReferenceNode != null) + { + parg = buildFieldReference(FTSRange.ARG_PROPERTY, specifiedFieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + } + } + if (parg != null) + { + CommonTree template = templateTrees.get(parg.getPropertyName().toLowerCase()); + if (template != null) + { + testNode = copyAndReplace(template, testNode); + } + } + else + { + if(hasOptionalFieldReference(testNode)) + { + if (isStarWithNoField(testNode)) + { + testNode = copyAndReplace(templateTrees.get(KEY_REPLACELONESTAR.toLowerCase()), testNode); + } + else + { + CommonTree template = templateTrees.get(defaultField.toLowerCase()); + if (template != null) + { + testNode = copyAndReplace(template, testNode); + } + } + } + } + + return testNode; + } + } + + static private Constraint buildFTSTest(CommonTree fieldReferenceNode, CommonTree argNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap, Map templateTrees, String defaultField) + { + CommonTree testNode = testNodeBuilder.build(fieldReferenceNode, argNode, factory, functionEvaluationContext, selector, columnMap, templateTrees, defaultField); + + Tree termNode; + Float fuzzy = findFuzzy(testNode); + switch (testNode.getType()) + { + case FTSParser.DISJUNCTION: + case FTSParser.FIELD_DISJUNCTION: + case FTSParser.CONJUNCTION: + case FTSParser.FIELD_CONJUNCTION: + return buildFTSConnective(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap, templateTrees, defaultField); + case FTSParser.TERM: + case FTSParser.FG_TERM: + termNode = testNode.getChild(0); + if (fuzzy == null) + { + switch (termNode.getType()) + { + case FTSParser.FTSPRE: + return buildPrefixTerm(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + case FTSParser.FTSWILD: + case FTSParser.STAR: + case FTSParser.QUESTION_MARK: + return buildWildTerm(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + default: + return buildTerm(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + } + } + else + { + switch (termNode.getType()) + { + case FTSParser.FTSPRE: + case FTSParser.FTSWILD: + case FTSParser.STAR: + case FTSParser.QUESTION_MARK: + throw new FTSQueryException("Fuzzy queries are not supported with wild cards"); + default: + return buildFuzzyTerm(fuzzy, fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + } + } + case FTSParser.EXACT_TERM: + case FTSParser.FG_EXACT_TERM: + termNode = testNode.getChild(0); + if (fuzzy == null) + { + switch (termNode.getType()) + { + case FTSParser.FTSPRE: + return buildExactPrefixTerm(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + case FTSParser.FTSWILD: + case FTSParser.STAR: + case FTSParser.QUESTION_MARK: + return buildExactWildTerm(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + default: + return buildExactTerm(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + } + } + else + { + switch (termNode.getType()) + { + case FTSParser.FTSPRE: + case FTSParser.FTSWILD: + case FTSParser.STAR: + case FTSParser.QUESTION_MARK: + throw new FTSQueryException("Fuzzy queries are not supported with wild cards"); + default: + return buildFuzzyTerm(fuzzy, fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + } + } + case FTSParser.PHRASE: + case FTSParser.FG_PHRASE: + return buildPhrase(fuzzy, fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + case FTSParser.EXACT_PHRASE: + case FTSParser.FG_EXACT_PHRASE: + return buildExactPhrase(fuzzy, fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + case FTSParser.SYNONYM: + case FTSParser.FG_SYNONYM: + termNode = testNode.getChild(0); + if (fuzzy == null) + { + switch (termNode.getType()) + { + case FTSParser.FTSPRE: + return buildPrefixTerm(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + case FTSParser.FTSWILD: + case FTSParser.STAR: + case FTSParser.QUESTION_MARK: + return buildWildTerm(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + default: + return buildExpandTerm(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + } + } + else + { + switch (termNode.getType()) + { + case FTSParser.FTSPRE: + case FTSParser.FTSWILD: + case FTSParser.STAR: + case FTSParser.QUESTION_MARK: + throw new FTSQueryException("Fuzzy queries are not supported with wild cards"); + default: + return buildFuzzyTerm(fuzzy, fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + } + } + case FTSParser.PROXIMITY: + case FTSParser.FG_PROXIMITY: + return buildProximity(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + case FTSParser.RANGE: + case FTSParser.FG_RANGE: + return buildRange(fieldReferenceNode, testNode, factory, functionEvaluationContext, selector, columnMap); + case FTSParser.FIELD_GROUP: + if (fieldReferenceNode != null) + { + throw new IllegalStateException("Already in field?"); + } + CommonTree newFieldReferenceNode = (CommonTree) testNode.getChild(0); + CommonTree fieldExperssion = (CommonTree) testNode.getChild(1); + return buildFTSConnective(newFieldReferenceNode, fieldExperssion, factory, functionEvaluationContext, selector, columnMap, templateTrees, defaultField); + default: + throw new FTSQueryException("Unsupported FTS option " + testNode.getText()); + } + } + + static private Constraint buildRange(CommonTree fieldReferenceNode, CommonTree testNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap) + { + String functionName = FTSRange.NAME; + Function function = factory.getFunction(functionName); + Map functionArguments = new LinkedHashMap(); + LiteralArgument larg = factory.createLiteralArgument(FTSRange.ARG_FROM_INC, DataTypeDefinition.BOOLEAN, testNode.getChild(0).getType() == FTSParser.INCLUSIVE); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSRange.ARG_FROM, DataTypeDefinition.TEXT, getText(testNode.getChild(1))); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSRange.ARG_TO, DataTypeDefinition.TEXT, getText(testNode.getChild(2))); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSRange.ARG_TO_INC, DataTypeDefinition.BOOLEAN, testNode.getChild(3).getType() == FTSParser.INCLUSIVE); + functionArguments.put(larg.getName(), larg); + if (fieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSRange.ARG_PROPERTY, fieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + else + { + CommonTree specifiedFieldReferenceNode = findFieldReference(testNode); + if (specifiedFieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSRange.ARG_PROPERTY, specifiedFieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + } + return factory.createFunctionalConstraint(function, functionArguments); + } + + static private Constraint buildProximity(CommonTree fieldReferenceNode, CommonTree testNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap) + { + String functionName = FTSProximity.NAME; + Function function = factory.getFunction(functionName); + Map functionArguments = new LinkedHashMap(); + LiteralArgument larg = factory.createLiteralArgument(FTSProximity.ARG_FIRST, DataTypeDefinition.TEXT, getText(testNode.getChild(0))); + functionArguments.put(larg.getName(), larg); + if (testNode.getChild(1).getChildCount() > 0) + { + larg = factory.createLiteralArgument(FTSProximity.ARG_SLOP, DataTypeDefinition.INT, getText(testNode.getChild(1).getChild(0))); + functionArguments.put(larg.getName(), larg); + } + larg = factory.createLiteralArgument(FTSProximity.ARG_LAST, DataTypeDefinition.TEXT, getText(testNode.getChild(2))); + functionArguments.put(larg.getName(), larg); + if (fieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSProximity.ARG_PROPERTY, fieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + else + { + CommonTree specifiedFieldReferenceNode = findFieldReference(testNode); + if (specifiedFieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSProximity.ARG_PROPERTY, specifiedFieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + } + return factory.createFunctionalConstraint(function, functionArguments); + } + + static private Constraint buildExpandTerm(CommonTree fieldReferenceNode, CommonTree testNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap) + { + String functionName = FTSTerm.NAME; + Function function = factory.getFunction(functionName); + Map functionArguments = new LinkedHashMap(); + LiteralArgument larg = factory.createLiteralArgument(FTSTerm.ARG_TERM, DataTypeDefinition.TEXT, getText(testNode.getChild(0))); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSTerm.ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, AnalysisMode.TOKENISE); + functionArguments.put(larg.getName(), larg); + if (fieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSTerm.ARG_PROPERTY, fieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + else + { + CommonTree specifiedFieldReferenceNode = findFieldReference(testNode); + if (specifiedFieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSTerm.ARG_PROPERTY, specifiedFieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + } + return factory.createFunctionalConstraint(function, functionArguments); + } + + static private Constraint buildPhrase(Float fuzzy, CommonTree fieldReferenceNode, CommonTree testNode, QueryModelFactory factory, + FunctionEvaluationContext functionEvaluationContext, Selector selector, Map columnMap) + { + String functionName = FTSPhrase.NAME; + Function function = factory.getFunction(functionName); + Map functionArguments = new LinkedHashMap(); + LiteralArgument larg = factory.createLiteralArgument(FTSPhrase.ARG_PHRASE, DataTypeDefinition.TEXT, getText(testNode.getChild(0))); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSPhrase.ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, AnalysisMode.DEFAULT); + functionArguments.put(larg.getName(), larg); + if (fuzzy != null) + { + larg = factory.createLiteralArgument(FTSPhrase.ARG_SLOP, DataTypeDefinition.INT, Integer.valueOf(fuzzy.intValue())); + functionArguments.put(larg.getName(), larg); + } + if (fieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSPhrase.ARG_PROPERTY, fieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + else + { + CommonTree specifiedFieldReferenceNode = findFieldReference(testNode); + if (specifiedFieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSPhrase.ARG_PROPERTY, specifiedFieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + } + return factory.createFunctionalConstraint(function, functionArguments); + } + + static private Constraint buildExactPhrase(Float fuzzy, CommonTree fieldReferenceNode, CommonTree testNode, QueryModelFactory factory, + FunctionEvaluationContext functionEvaluationContext, Selector selector, Map columnMap) + { + String functionName = FTSPhrase.NAME; + Function function = factory.getFunction(functionName); + Map functionArguments = new LinkedHashMap(); + LiteralArgument larg = factory.createLiteralArgument(FTSPhrase.ARG_PHRASE, DataTypeDefinition.TEXT, getText(testNode.getChild(0))); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSPhrase.ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, AnalysisMode.IDENTIFIER); + functionArguments.put(larg.getName(), larg); + if (fuzzy != null) + { + larg = factory.createLiteralArgument(FTSPhrase.ARG_SLOP, DataTypeDefinition.INT, Integer.valueOf(fuzzy.intValue())); + functionArguments.put(larg.getName(), larg); + } + if (fieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSPhrase.ARG_PROPERTY, fieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + else + { + CommonTree specifiedFieldReferenceNode = findFieldReference(testNode); + if (specifiedFieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSPhrase.ARG_PROPERTY, specifiedFieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + } + return factory.createFunctionalConstraint(function, functionArguments); + } + + @SuppressWarnings("unchecked") + static private Constraint buildExactTerm(CommonTree fieldReferenceNode, CommonTree testNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap) + { + String functionName = FTSTerm.NAME; + Function function = factory.getFunction(functionName); + Map functionArguments = new LinkedHashMap(); + LiteralArgument larg = factory.createLiteralArgument(FTSTerm.ARG_TERM, DataTypeDefinition.TEXT, getText((List) testNode.getChildren())); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSTerm.ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, AnalysisMode.IDENTIFIER); + functionArguments.put(larg.getName(), larg); + if (fieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSTerm.ARG_PROPERTY, fieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + else + { + CommonTree specifiedFieldReferenceNode = findFieldReference(testNode); + if (specifiedFieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSTerm.ARG_PROPERTY, specifiedFieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + } + return factory.createFunctionalConstraint(function, functionArguments); + } + + @SuppressWarnings("unchecked") + static private Constraint buildTerm(CommonTree fieldReferenceNode, CommonTree testNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap) + { + String functionName = FTSTerm.NAME; + Function function = factory.getFunction(functionName); + Map functionArguments = new LinkedHashMap(); + LiteralArgument larg = factory.createLiteralArgument(FTSTerm.ARG_TERM, DataTypeDefinition.TEXT, getText((List) testNode.getChildren())); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSTerm.ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, AnalysisMode.DEFAULT); + functionArguments.put(larg.getName(), larg); + if (fieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSTerm.ARG_PROPERTY, fieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + else + { + CommonTree specifiedFieldReferenceNode = findFieldReference(testNode); + if (specifiedFieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSTerm.ARG_PROPERTY, specifiedFieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + } + return factory.createFunctionalConstraint(function, functionArguments); + } + + static private CommonTree copyAndReplace(CommonTree source, CommonTree insert) + { + CommonTree newNode = new CommonTree(source); + if (source.getChildCount() > 0) + { + for (Object current : source.getChildren()) + { + CommonTree child = (CommonTree) current; + if (child.getType() == FTSParser.TEMPLATE) + { + if (child.getChildCount() > 1) + { + CommonTree disjunction = new CommonTree(new DisjunctionToken()); + newNode.addChild(disjunction); + for (Object currentfieldReferenceNode : child.getChildren()) + { + CommonTree fieldReferenceNode = (CommonTree) currentfieldReferenceNode; + CommonTree def = new CommonTree(new DefaultToken()); + disjunction.addChild(def); + CommonTree newChild = insertTreeAndFixFieldRefs(insert, fieldReferenceNode); + def.addChild(newChild); + } + + } + else + { + CommonTree fieldReferenceNode = findFieldReference(child); + CommonTree newChild = insertTreeAndFixFieldRefs(insert, fieldReferenceNode); + newNode.addChild(newChild); + } + } + else + { + CommonTree newChild = copyAndReplace(child, insert); + newNode.addChild(newChild); + } + } + } + return newNode; + } + + static class DisjunctionToken implements Token + { + + public int getChannel() + { + // TODO Auto-generated method stub + return 0; + } + + public int getCharPositionInLine() + { + // TODO Auto-generated method stub + return 0; + } + + public CharStream getInputStream() + { + // TODO Auto-generated method stub + return null; + } + + public int getLine() + { + // TODO Auto-generated method stub + return 0; + } + + public String getText() + { + // TODO Auto-generated method stub + return null; + } + + public int getTokenIndex() + { + // TODO Auto-generated method stub + return 0; + } + + public int getType() + { + return FTSParser.DISJUNCTION; + } + + public void setChannel(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setCharPositionInLine(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setInputStream(CharStream arg0) + { + // TODO Auto-generated method stub + + } + + public void setLine(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setText(String arg0) + { + // TODO Auto-generated method stub + + } + + public void setTokenIndex(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setType(int arg0) + { + // TODO Auto-generated method stub + + } + + } + + static class WordToken implements Token + { + String text; + + WordToken(String text) + { + this.text = text; + } + + public int getChannel() + { + // TODO Auto-generated method stub + return 0; + } + + public int getCharPositionInLine() + { + // TODO Auto-generated method stub + return 0; + } + + public CharStream getInputStream() + { + // TODO Auto-generated method stub + return null; + } + + public int getLine() + { + // TODO Auto-generated method stub + return 0; + } + + public String getText() + { + return text; + } + + public int getTokenIndex() + { + // TODO Auto-generated method stub + return 0; + } + + public int getType() + { + return FTSParser.FTSWORD; + } + + public void setChannel(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setCharPositionInLine(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setInputStream(CharStream arg0) + { + // TODO Auto-generated method stub + + } + + public void setLine(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setText(String arg0) + { + // TODO Auto-generated method stub + + } + + public void setTokenIndex(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setType(int arg0) + { + // TODO Auto-generated method stub + + } + + } + + static class PhraseToken implements Token + { + public int getChannel() + { + // TODO Auto-generated method stub + return 0; + } + + public int getCharPositionInLine() + { + // TODO Auto-generated method stub + return 0; + } + + public CharStream getInputStream() + { + // TODO Auto-generated method stub + return null; + } + + public int getLine() + { + // TODO Auto-generated method stub + return 0; + } + + public String getText() + { + return null; + } + + public int getTokenIndex() + { + // TODO Auto-generated method stub + return 0; + } + + public int getType() + { + return FTSParser.PHRASE; + } + + public void setChannel(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setCharPositionInLine(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setInputStream(CharStream arg0) + { + // TODO Auto-generated method stub + + } + + public void setLine(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setText(String arg0) + { + // TODO Auto-generated method stub + + } + + public void setTokenIndex(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setType(int arg0) + { + // TODO Auto-generated method stub + + } + + } + + static class ConjunctionToken implements Token + { + + public int getChannel() + { + // TODO Auto-generated method stub + return 0; + } + + public int getCharPositionInLine() + { + // TODO Auto-generated method stub + return 0; + } + + public CharStream getInputStream() + { + // TODO Auto-generated method stub + return null; + } + + public int getLine() + { + // TODO Auto-generated method stub + return 0; + } + + public String getText() + { + // TODO Auto-generated method stub + return null; + } + + public int getTokenIndex() + { + // TODO Auto-generated method stub + return 0; + } + + public int getType() + { + return FTSParser.CONJUNCTION; + } + + public void setChannel(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setCharPositionInLine(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setInputStream(CharStream arg0) + { + // TODO Auto-generated method stub + + } + + public void setLine(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setText(String arg0) + { + // TODO Auto-generated method stub + + } + + public void setTokenIndex(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setType(int arg0) + { + // TODO Auto-generated method stub + + } + + } + + static class DefaultToken implements Token + { + + public int getChannel() + { + // TODO Auto-generated method stub + return 0; + } + + public int getCharPositionInLine() + { + // TODO Auto-generated method stub + return 0; + } + + public CharStream getInputStream() + { + // TODO Auto-generated method stub + return null; + } + + public int getLine() + { + // TODO Auto-generated method stub + return 0; + } + + public String getText() + { + // TODO Auto-generated method stub + return null; + } + + public int getTokenIndex() + { + // TODO Auto-generated method stub + return 0; + } + + public int getType() + { + return FTSParser.DEFAULT; + } + + public void setChannel(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setCharPositionInLine(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setInputStream(CharStream arg0) + { + // TODO Auto-generated method stub + + } + + public void setLine(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setText(String arg0) + { + // TODO Auto-generated method stub + + } + + public void setTokenIndex(int arg0) + { + // TODO Auto-generated method stub + + } + + public void setType(int arg0) + { + // TODO Auto-generated method stub + + } + + } + + static private CommonTree copy(CommonTree source) + { + CommonTree newNode = new CommonTree(source); + if (source.getChildCount() > 0) + { + for (Object current : source.getChildren()) + { + CommonTree child = (CommonTree) current; + CommonTree newChild = copy(child); + newNode.addChild(newChild); + } + } + return newNode; + } + + private static CommonTree insertTreeAndFixFieldRefs(CommonTree source, CommonTree fieldReferenceNode) + { + boolean foundRef = false; + CommonTree newNode = new CommonTree(source); + if (source.getChildCount() > 0) + { + for (Object current : source.getChildren()) + { + CommonTree child = (CommonTree) current; + if (child.getType() == FTSParser.FIELD_REF) + { + CommonTree newChild = copy(fieldReferenceNode); + newNode.addChild(newChild); + foundRef = true; + } + else + { + CommonTree newChild = insertTreeAndFixFieldRefs(child, fieldReferenceNode); + newNode.addChild(newChild); + } + } + } + // if no ref found and it should have one we are creating one in place of the default + if(!foundRef && hasOptionalFieldReference(source)) + { + CommonTree newChild = copy(fieldReferenceNode); + newNode.addChild(newChild); + } + return newNode; + } + + private static boolean hasOptionalFieldReference(CommonTree node) + { + switch (node.getType()) + { + case FTSParser.TERM: + case FTSParser.EXACT_TERM: + case FTSParser.PHRASE: + case FTSParser.EXACT_PHRASE: + case FTSParser.SYNONYM: + case FTSParser.PROXIMITY: + case FTSParser.RANGE: + return true; + default: + return false; + } + } + + private static boolean isStarWithNoField(CommonTree testNode) + { + if (testNode.getType() == FTSParser.TERM && testNode.getChildCount() == 1) + { + CommonTree child = (CommonTree) testNode.getChild(0); + if (child.getType() == FTSParser.STAR) + { + return true; + } + } + return false; + } + + static private Constraint buildFuzzyTerm(Float fuzzy, CommonTree fieldReferenceNode, CommonTree testNode, QueryModelFactory factory, + FunctionEvaluationContext functionEvaluationContext, Selector selector, Map columnMap) + { + String functionName = FTSFuzzyTerm.NAME; + Function function = factory.getFunction(functionName); + Map functionArguments = new LinkedHashMap(); + LiteralArgument larg = factory.createLiteralArgument(FTSFuzzyTerm.ARG_TERM, DataTypeDefinition.TEXT, getText(testNode.getChild(0))); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSFuzzyTerm.ARG_MIN_SIMILARITY, DataTypeDefinition.FLOAT, fuzzy); + functionArguments.put(larg.getName(), larg); + if (fieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSFuzzyTerm.ARG_PROPERTY, fieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + else + { + CommonTree specifiedFieldReferenceNode = findFieldReference(testNode); + if (specifiedFieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSFuzzyTerm.ARG_PROPERTY, specifiedFieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + } + return factory.createFunctionalConstraint(function, functionArguments); + } + + @SuppressWarnings("unchecked") + static private Constraint buildWildTerm(CommonTree fieldReferenceNode, CommonTree testNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap) + { + String functionName = FTSWildTerm.NAME; + Function function = factory.getFunction(functionName); + Map functionArguments = new LinkedHashMap(); + LiteralArgument larg = factory.createLiteralArgument(FTSWildTerm.ARG_TERM, DataTypeDefinition.TEXT, getText((List) testNode.getChildren())); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSPhrase.ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, AnalysisMode.DEFAULT); + functionArguments.put(larg.getName(), larg); + if (fieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSWildTerm.ARG_PROPERTY, fieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + else + { + CommonTree specifiedFieldReferenceNode = findFieldReference(testNode); + if (specifiedFieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSWildTerm.ARG_PROPERTY, specifiedFieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + } + return factory.createFunctionalConstraint(function, functionArguments); + } + + @SuppressWarnings("unchecked") + static private Constraint buildExactWildTerm(CommonTree fieldReferenceNode, CommonTree testNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap) + { + String functionName = FTSWildTerm.NAME; + Function function = factory.getFunction(functionName); + Map functionArguments = new LinkedHashMap(); + LiteralArgument larg = factory.createLiteralArgument(FTSWildTerm.ARG_TERM, DataTypeDefinition.TEXT, getText((List) testNode.getChildren())); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSPhrase.ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, AnalysisMode.IDENTIFIER); + functionArguments.put(larg.getName(), larg); + if (fieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSWildTerm.ARG_PROPERTY, fieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + else + { + CommonTree specifiedFieldReferenceNode = findFieldReference(testNode); + if (specifiedFieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSWildTerm.ARG_PROPERTY, specifiedFieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + } + return factory.createFunctionalConstraint(function, functionArguments); + } + + @SuppressWarnings("unchecked") + static private Constraint buildPrefixTerm(CommonTree fieldReferenceNode, CommonTree testNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap) + { + String functionName = FTSPrefixTerm.NAME; + Function function = factory.getFunction(functionName); + Map functionArguments = new LinkedHashMap(); + LiteralArgument larg = factory.createLiteralArgument(FTSPrefixTerm.ARG_TERM, DataTypeDefinition.TEXT, getText((List) testNode.getChildren())); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSPhrase.ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, AnalysisMode.DEFAULT); + functionArguments.put(larg.getName(), larg); + if (fieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSPrefixTerm.ARG_PROPERTY, fieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + else + { + CommonTree specifiedFieldReferenceNode = findFieldReference(testNode); + if (specifiedFieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSPrefixTerm.ARG_PROPERTY, specifiedFieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + } + return factory.createFunctionalConstraint(function, functionArguments); + } + + @SuppressWarnings("unchecked") + static private Constraint buildExactPrefixTerm(CommonTree fieldReferenceNode, CommonTree testNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap) + { + String functionName = FTSPrefixTerm.NAME; + Function function = factory.getFunction(functionName); + Map functionArguments = new LinkedHashMap(); + LiteralArgument larg = factory.createLiteralArgument(FTSPrefixTerm.ARG_TERM, DataTypeDefinition.TEXT, getText((List) testNode.getChildren())); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSPhrase.ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, AnalysisMode.IDENTIFIER); + functionArguments.put(larg.getName(), larg); + if (fieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSPrefixTerm.ARG_PROPERTY, fieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + else + { + CommonTree specifiedFieldReferenceNode = findFieldReference(testNode); + if (specifiedFieldReferenceNode != null) + { + PropertyArgument parg = buildFieldReference(FTSPrefixTerm.ARG_PROPERTY, specifiedFieldReferenceNode, factory, functionEvaluationContext, selector, columnMap); + functionArguments.put(parg.getName(), parg); + } + } + return factory.createFunctionalConstraint(function, functionArguments); + } + + static private CommonTree findFieldReference(CommonTree node) + { + for (int i = 0, l = node.getChildCount(); i < l; i++) + { + CommonTree child = (CommonTree) node.getChild(i); + if (child.getType() == FTSParser.FIELD_REF) + { + return child; + } + } + return null; + } + + static private Float findFuzzy(Tree node) + { + for (int i = 0, l = node.getChildCount(); i < l; i++) + { + CommonTree child = (CommonTree) node.getChild(i); + if (child.getType() == FTSParser.FUZZY) + { + String fuzzyString = child.getChild(0).getText(); + float fuzzy = Float.parseFloat(fuzzyString); + return Float.valueOf(fuzzy); + } + } + return null; + } + + static public PropertyArgument buildFieldReference(String argumentName, CommonTree fieldReferenceNode, QueryModelFactory factory, + FunctionEvaluationContext functionEvaluationContext, Selector selector, Map columnMap) + { + if (fieldReferenceNode.getType() != FTSParser.FIELD_REF) + { + throw new FTSQueryException("Not column ref ..." + fieldReferenceNode.getText()); + } + String fieldName = getText(fieldReferenceNode.getChild(0)); + if (columnMap != null) + { + for (Column column : columnMap.values()) + { + if (column.getAlias().equals(fieldName)) + { + // TODO: Check selector matches ... + PropertyArgument arg = (PropertyArgument) column.getFunctionArguments().get(PropertyAccessor.ARG_PROPERTY); + fieldName = arg.getPropertyName(); + break; + } + } + } + + // prepend prefixes and name spaces + + if (fieldReferenceNode.getChildCount() > 1) + { + CommonTree child = (CommonTree) fieldReferenceNode.getChild(1); + if (child.getType() == FTSParser.PREFIX) + { + fieldName = getText(child.getChild(0)) + ":" + fieldName; + } + else if (child.getType() == FTSParser.NAME_SPACE) + { + fieldName = getText(child.getChild(0)) + fieldName; + } + } + + String alias = ""; + if (selector != null) + { + functionEvaluationContext.checkFieldApplies(selector, fieldName); + alias = selector.getAlias(); + } + + return factory.createPropertyArgument(argumentName, functionEvaluationContext.isQueryable(fieldName), functionEvaluationContext.isOrderable(fieldName), alias, fieldName); + } + + static private String getText(List nodes) + { + StringBuilder builder = new StringBuilder(); + for(Object node : nodes) + { + builder.append(getText((Tree)node, false)); + } + return builder.toString(); + } + + static private String getText(Tree node) + { + return getText(node, true); + } + + static private String getText(Tree node, boolean returnTextFromUnknownNodes) + { + String text = node.getText(); + int index; + switch (node.getType()) + { + case FTSParser.FTSWORD: + case FTSParser.FTSPRE: + case FTSParser.FTSWILD: + index = text.indexOf('\\'); + if (index == -1) + { + return text; + } + else + { + return unescape(text); + } + case FTSParser.FTSPHRASE: + String phrase = text.substring(1, text.length() - 1); + index = phrase.indexOf('\\'); + if (index == -1) + { + return phrase; + } + else + { + return unescape(phrase); + } + case FTSParser.ID: + index = text.indexOf('\\'); + if (index == -1) + { + return ISO9075.decode(text); + } + else + { + return ISO9075.decode(unescape(text)); + } + case FTSParser.URI: + case FTSParser.OR: + case FTSParser.AND: + case FTSParser.NOT: + case FTSParser.TILDA: + case FTSParser.PLUS: + case FTSParser.MINUS: + case FTSParser.COLON: + case FTSParser.STAR: + case FTSParser.DOTDOT: + case FTSParser.DOT: + case FTSParser.AMP: + case FTSParser.EXCLAMATION: + case FTSParser.BAR: + case FTSParser.EQUALS: + case FTSParser.QUESTION_MARK: + case FTSParser.TO: + case FTSParser.COMMA: + case FTSParser.CARAT: + case FTSParser.DOLLAR: + case FTSParser.AT: + case FTSParser.PERCENT: + case FTSParser.DECIMAL_INTEGER_LITERAL: + case FTSParser.FLOATING_POINT_LITERAL: + case FTSParser.DATETIME: + return text; + default: + if(returnTextFromUnknownNodes) + { + return text; + } + else + { + return ""; + } + } + } + + static private String unescape(String string) + { + StringBuilder builder = new StringBuilder(string.length()); + boolean lastWasEscape = false; + + for (int i = 0; i < string.length(); i++) + { + char c = string.charAt(i); + if (lastWasEscape) + { + if (c == 'u') + { + if((i+4) < string.length()) + { + char encoded = (char)Integer.parseInt(string.substring(i+1, i+5), 16); + builder.append(encoded); + i += 4; + } + else + { + throw new UnsupportedOperationException(string); + } + } + else + { + builder.append(c); + } + lastWasEscape = false; + } + else + { + if (c == '\\') + { + lastWasEscape = true; + } + else + { + builder.append(c); + } + } + } + if (lastWasEscape) + { + throw new FTSQueryException("Escape character at end of string " + string); + } + + return builder.toString(); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/GenerateUnicodeRanges.java b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/GenerateUnicodeRanges.java new file mode 100644 index 0000000000..5ee226a89c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/parsers/GenerateUnicodeRanges.java @@ -0,0 +1,129 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.parsers; + + +/** + * @author Andy + */ +public class GenerateUnicodeRanges +{ + + /** + * @param args String[] + */ + public static void main(String[] args) + { + + int start = 0; + int last = 0; + for (int i = 0; i < 0xFFFF; i++) + { + //if (Character.isSpaceChar(i)) + switch(Character.getType(i)) + { + case Character.LOWERCASE_LETTER: // V1 V2 V3-SW + case Character.MODIFIER_LETTER: // V1 V2 V3-SW + case Character.OTHER_LETTER: // V1 V2 V3-SW + case Character.TITLECASE_LETTER: // V1 V2 V3-SW + case Character.UPPERCASE_LETTER: // V1 V2 V3-SW + case Character.COMBINING_SPACING_MARK: // V2 V3-SW + case Character.ENCLOSING_MARK: // V2 V3-SW + case Character.NON_SPACING_MARK: // V2 V3-SW + case Character.DECIMAL_DIGIT_NUMBER: // V1 V2 V3-SW + case Character.LETTER_NUMBER: // V2 V3-SW + case Character.OTHER_NUMBER: // V2 V3-SW + case Character.CURRENCY_SYMBOL: // V2 V3-SW + case Character.OTHER_SYMBOL: // V2 V3-SW + + case Character.CONNECTOR_PUNCTUATION: // V3-W + case Character.DASH_PUNCTUATION: // V3-W + case Character.OTHER_PUNCTUATION: // V3-W + case Character.MATH_SYMBOL: // V3-W + if (last == 0) + { + start = i; + } + + if ((last + 1 == i) || (start == i)) + { + last = i; + } + else + { + if (start > 0) + { + if (start == (i - 1)) + { + System.out.println(String.format(" | '\\u%04x'", Integer.valueOf(start))); + } + else + { + System.out.println(String.format(" | '\\u%04x'..'\\u%04x'", Integer.valueOf(start), Integer.valueOf(last))); + } + start = i; + last = i; + } + } + break; + + + case Character.CONTROL: // X + case Character.FORMAT: // X + case Character.PRIVATE_USE: // X + case Character.SURROGATE: // X + //case Character.CONNECTOR_PUNCTUATION: // V3-W + //case Character.DASH_PUNCTUATION: // V3-W + case Character.END_PUNCTUATION: // X + case Character.FINAL_QUOTE_PUNCTUATION: //X + case Character.INITIAL_QUOTE_PUNCTUATION: // X + //case Character.OTHER_PUNCTUATION: // V3-W + case Character.START_PUNCTUATION: // X + case Character.MODIFIER_SYMBOL: // X + //case Character.MATH_SYMBOL: // V3-W + case Character.LINE_SEPARATOR: + case Character.PARAGRAPH_SEPARATOR: + case Character.SPACE_SEPARATOR: + if (start > 0) + { + if (start == (i - 1)) + { + System.out.println(String.format(" | '\\u%04x'", Integer.valueOf(start))); + } + else + { + System.out.println(String.format(" | '\\u%04x'..'\\u%04x'", Integer.valueOf(start), Integer.valueOf(last))); + } + start = 0; + last = 0; + } + break; + } + + } + + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Argument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Argument.java new file mode 100644 index 0000000000..6f89cfc348 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Argument.java @@ -0,0 +1,45 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import java.io.Serializable; + +/** + * An argument to a function + * + * @author andyh + * + */ +public interface Argument +{ + public String getName(); + + public Serializable getValue(FunctionEvaluationContext context); + + public boolean isOrderable(); + + public boolean isQueryable(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/ArgumentDefinition.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/ArgumentDefinition.java new file mode 100644 index 0000000000..c190589043 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/ArgumentDefinition.java @@ -0,0 +1,43 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import org.alfresco.service.namespace.QName; + +/** + * @author andyh + * + */ +public interface ArgumentDefinition +{ + public String getName(); + + public QName getType(); + + public Multiplicity getMutiplicity(); + + public boolean isMandatory(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Column.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Column.java new file mode 100644 index 0000000000..0dcfe34962 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Column.java @@ -0,0 +1,46 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + + + +/** + * @author andyh + * + */ +public interface Column extends FunctionInvokation +{ + /** + * Get the column alias. + * + * @return String + */ + public String getAlias(); + + public boolean isOrderable(); + + public boolean isQueryable(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Conjunction.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Conjunction.java new file mode 100644 index 0000000000..3a83f86857 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Conjunction.java @@ -0,0 +1,40 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import java.util.List; + +/** + * @author andyh + * + */ +public interface Conjunction extends Constraint +{ + /** + * Get the list of constraints which must all be met + */ + public List getConstraints(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Constraint.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Constraint.java new file mode 100644 index 0000000000..f4fdda1c49 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Constraint.java @@ -0,0 +1,53 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +/** + * A constraint + * + * @author andyh + * + */ +public interface Constraint +{ + public enum Occur + { + DEFAULT, + MANDATORY, + OPTIONAL, + EXCLUDE + } + + public boolean evaluate(); + + public Occur getOccur(); + + public void setOccur(Occur occur); + + public float getBoost(); + + public void setBoost(float boost); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Disjunction.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Disjunction.java new file mode 100644 index 0000000000..a90ba95434 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Disjunction.java @@ -0,0 +1,41 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import java.util.List; + +/** + * @author andyh + * + */ +public interface Disjunction extends Constraint +{ + /** + * Get the list of constraints for which at least one must be met. + * + */ + public List getConstraints(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/DynamicArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/DynamicArgument.java new file mode 100644 index 0000000000..9d0720e109 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/DynamicArgument.java @@ -0,0 +1,37 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +/** + * A dynamic argument (e.g. non-literal and not a parameter) + * + * @author andyh + * + */ +public interface DynamicArgument extends Argument +{ + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Function.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Function.java new file mode 100644 index 0000000000..9700ee15ef --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Function.java @@ -0,0 +1,75 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.service.namespace.QName; + +/** + * @author andyh + */ +public interface Function +{ + /** + * Evaluation a function + * + * @param context FunctionEvaluationContext + * @return Serializable + */ + public Serializable getValue(Map args, FunctionEvaluationContext context); + + /** + * Get the return type for the function + * + * @return QName + */ + public QName getReturnType(); + + /** + * Get the function name + * + * @return String + */ + public String getName(); + + /** + * Get the argument Definitions + * @return LinkedHashMap + */ + public LinkedHashMap getArgumentDefinitions(); + + + /** + * Get the argument Definition + * @return ArgumentDefinition + */ + public ArgumentDefinition getArgumentDefinition(String name); + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionArgument.java new file mode 100644 index 0000000000..ebae7bb29b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionArgument.java @@ -0,0 +1,35 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +/** + * @author andyh + * + */ +public interface FunctionArgument extends DynamicArgument, FunctionInvokation +{ + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionEvaluationContext.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionEvaluationContext.java new file mode 100644 index 0000000000..44fc1080bf --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionEvaluationContext.java @@ -0,0 +1,221 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Map; + +import org.alfresco.repo.search.adaptor.lucene.LuceneFunction; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; + +/** + * The function evaluation context for lucene query implementations. + * + * This context is used at query time and also when navigating the results to get column values. + * + * @author andyh + */ +public interface FunctionEvaluationContext +{ + /** + * @return the matching nodes by selector (at navigation time) + */ + public Map getNodeRefs(); + + /** + * @return the scores by selector (at navigation time) + */ + public Map getScores(); + + /** + * Get a property + * @param nodeRef NodeRef + * @param propertyName String + * @return the property (at navigation time) + */ + public Serializable getProperty(NodeRef nodeRef, String propertyName); + + /** + * @return the node service + */ + public NodeService getNodeService(); + + /** + * @return the score (at navigation time) + */ + public Float getScore(); + + /** + * @param propertyName String + * @param value Serializable + * @param mode PredicateMode + * @param luceneFunction LuceneFunction + * @return the query + * @throws E + */ + public Q buildLuceneEquality(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E; + + /** + * Note: null and not null are not required to support functions from the spec + * @param propertyName String + * @param not Boolean + * @return the query + * @throws E + */ + public Q buildLuceneExists(LuceneQueryParserAdaptor lqpa, String propertyName, Boolean not) throws E; + + /** + * @param propertyName String + * @param value Serializable + * @param mode PredicateMode + * @param luceneFunction LuceneFunction + * @return the query + * @throws E + */ + public Q buildLuceneGreaterThan(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E; + + /** + * @param propertyName String + * @param value Serializable + * @param mode PredicateMode + * @param luceneFunction LuceneFunction + * @return the query + * @throws E + */ + public Q buildLuceneGreaterThanOrEquals(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E; + + /** + * @param propertyName String + * @param value Serializable + * @param mode PredicateMode + * @param luceneFunction LuceneFunction + * @return the query + * @throws E + */ + public Q buildLuceneLessThan(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E; + + /** + * @param propertyName String + * @param value Serializable + * @param mode PredicateMode + * @param luceneFunction LuceneFunction + * @return the query + * @throws E + */ + public Q buildLuceneLessThanOrEquals(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E; + + /** + * Note: Like is not required to support functions from the spec + * @param propertyName String + * @param value Serializable + * @param not Boolean + * @return the query + * @throws E + */ + public Q buildLuceneLike(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, Boolean not) throws E; + + /** + * @param propertyName String + * @param value Serializable + * @param mode PredicateMode + * @param luceneFunction LuceneFunction + * @return the query + * @throws E + */ + public Q buildLuceneInequality(LuceneQueryParserAdaptor lqpa, String propertyName, Serializable value, PredicateMode mode, LuceneFunction luceneFunction) throws E; + + /** + * Note: In is not required to support functions from the spec + * @param propertyName String + * @param not Boolean + * @param mode PredicateMode + * @return the query + * @throws E + */ + public Q buildLuceneIn(LuceneQueryParserAdaptor lqpa, String propertyName, Collection values, Boolean not, PredicateMode mode) throws E; + + /** + * @param propertyName String + * @return the field used for sorting the given property + * @throws E + */ + public String getLuceneSortField(LuceneQueryParserAdaptor lqpa, String propertyName) throws E; + + /** + * @param propertyName String + * @return - is this an object id + */ + public boolean isObjectId(String propertyName); + + /** + * @param propertyName String + * @return is this property queryable + */ + public boolean isQueryable(String propertyName); + + /** + * @param propertyName String + * @return Is this property orderable + */ + public boolean isOrderable(String propertyName); + + /** + * @param propertyName String + * @return the lucene field name for the property + */ + public String getLuceneFieldName(String propertyName); + + /** + * @param functionArgument FunctionArgument + * @return the lucene function appropriate to a function argument + */ + public LuceneFunction getLuceneFunction(FunctionArgument functionArgument); + + /** + * @param selector Selector + * @param propertyName String + */ + public void checkFieldApplies(Selector selector, String propertyName); + + /** + * Is this a multi-valued property? + * @param propertyName String + * @return boolean + */ + public boolean isMultiValued(String propertyName); + + public String getAlfrescoPropertyName(String propertyName); + + /** + * @param staticValue String + * @return String + */ + public String getAlfrescoTypeName(String staticValue); + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionInvokation.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionInvokation.java new file mode 100644 index 0000000000..c5d0103bd1 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionInvokation.java @@ -0,0 +1,48 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import java.util.Map; + +/** + * @author andyh + */ +public interface FunctionInvokation +{ + /** + * Get the function + * + * @return Function + */ + public Function getFunction(); + + /** + * Get the functions arguments. + * + * @return Map + */ + public Map getFunctionArguments(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionalConstraint.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionalConstraint.java new file mode 100644 index 0000000000..4913c92319 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/FunctionalConstraint.java @@ -0,0 +1,37 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + + +/** + * A constraint defined by a function that returns a boolean value. + * + * @author andyh + */ +public interface FunctionalConstraint extends Constraint, FunctionInvokation +{ + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Join.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Join.java new file mode 100644 index 0000000000..0d591c1724 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Join.java @@ -0,0 +1,52 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +/** + * @author andyh + * + */ +public interface Join extends Source +{ + /** + * The source for the left hand side of the join + * @return Source + */ + public Source getLeft(); + + /** + * The source for the right hand side of the join + * @return Source + */ + public Source getRight(); + + /** + * Get the join condition. + * Not all constraints are valid join conditions + * @return Constraint + */ + public Constraint getJoinCondition(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/JoinType.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/JoinType.java new file mode 100644 index 0000000000..42db10d5fe --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/JoinType.java @@ -0,0 +1,50 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +/** + * @author andyh + * + */ +public enum JoinType +{ + /** + * Inner join + */ + INNER, + /** + * Left (outer) join + */ + LEFT, + /** + * Right (outer) join + */ + RIGHT, + /** + * No Join + */ + NONE +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/ListArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/ListArgument.java new file mode 100644 index 0000000000..1a385186e4 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/ListArgument.java @@ -0,0 +1,37 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import java.util.List; + +/** + * @author andyh + * + */ +public interface ListArgument extends StaticArgument +{ + public List getArguments(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/LiteralArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/LiteralArgument.java new file mode 100644 index 0000000000..c963e0a463 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/LiteralArgument.java @@ -0,0 +1,36 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import org.alfresco.service.namespace.QName; + +/** + * @author andyh + */ +public interface LiteralArgument extends StaticArgument +{ + public QName getType(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Multiplicity.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Multiplicity.java new file mode 100644 index 0000000000..4c714846dc --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Multiplicity.java @@ -0,0 +1,34 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +/** + * @author andyh + */ +public enum Multiplicity +{ + SINGLE_VALUED, MULTI_VALUED, ANY; +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Order.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Order.java new file mode 100644 index 0000000000..05ce23ae4a --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Order.java @@ -0,0 +1,35 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +/** + * @author andyh + * + */ +public enum Order +{ + ASCENDING, DESCENDING; +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Ordering.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Ordering.java new file mode 100644 index 0000000000..5e660fa5e9 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Ordering.java @@ -0,0 +1,37 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +/** + * @author andyh + * + */ +public interface Ordering +{ + public Column getColumn(); + + public Order getOrder(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/ParameterArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/ParameterArgument.java new file mode 100644 index 0000000000..13f65a0fd9 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/ParameterArgument.java @@ -0,0 +1,34 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +/** + * @author andyh + */ +public interface ParameterArgument extends StaticArgument +{ + public String getParameterName(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/PredicateMode.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/PredicateMode.java new file mode 100644 index 0000000000..e7274763c0 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/PredicateMode.java @@ -0,0 +1,35 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +/** + * @author andyh + * + */ +public enum PredicateMode +{ + ANY, SINGLE_VALUED_PROPERTY; +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/PropertyArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/PropertyArgument.java new file mode 100644 index 0000000000..49d5886f68 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/PropertyArgument.java @@ -0,0 +1,37 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + + +/** + * @author andyh + */ +public interface PropertyArgument extends DynamicArgument +{ + public String getSelector(); + + public String getPropertyName(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Query.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Query.java new file mode 100644 index 0000000000..1f0c104b06 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Query.java @@ -0,0 +1,69 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import java.util.List; + +/** + * @author andyh + * + */ +public interface Query +{ + /** + * Get the columns to return from the query + * + * This may not be null and must contain at least one entry. + * "*" "A.*" etc column specifications are not supported. + * These should have been previously expanded between any query parse and building the query model. + * + */ + public List getColumns(); + + /** + * Get the constraints for the query. + * This is as defined - with no hoisting etc. + * Hoisting is the problem of the implementation layer. + * + * May be null for unconstrained. + * + * @return Constraint + */ + public Constraint getConstraint(); + + /** + * Get any orderings (may be an empty list or null) + * + */ + public List getOrderings(); + + /** + * Get the source for the query + * Must not be null. + * @return Source + */ + public Source getSource(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryEngine.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryEngine.java new file mode 100644 index 0000000000..e543104e5f --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryEngine.java @@ -0,0 +1,37 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +/** + * @author andyh + * + */ +public interface QueryEngine +{ + public QueryEngineResults executeQuery(Query query, QueryOptions options, FunctionEvaluationContext functionContext); + + public QueryModelFactory getQueryModelFactory(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryEngineResults.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryEngineResults.java new file mode 100644 index 0000000000..9349f38709 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryEngineResults.java @@ -0,0 +1,51 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.service.cmr.search.ResultSet; + +/** + * Encapsulate Query engine results + * + * @author andyh + */ +public class QueryEngineResults +{ + private Map, ResultSet> results; + + public QueryEngineResults(Map, ResultSet> results) + { + this.results = results; + } + + public Map, ResultSet> getResults() + { + return results; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryModelException.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryModelException.java new file mode 100644 index 0000000000..cdede6e330 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryModelException.java @@ -0,0 +1,82 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import org.alfresco.error.AlfrescoRuntimeException; + +/** + * @author andyh + * + */ +public class QueryModelException extends AlfrescoRuntimeException +{ + + /** + * + */ + private static final long serialVersionUID = 5103880924975096422L; + + /** + * @param msgId String + */ + public QueryModelException(String msgId) + { + super(msgId); + // TODO Auto-generated constructor stub + } + + /** + * @param msgId String + * @param msgParams Object[] + */ + public QueryModelException(String msgId, Object[] msgParams) + { + super(msgId, msgParams); + // TODO Auto-generated constructor stub + } + + /** + * @param msgId String + * @param cause Throwable + */ + public QueryModelException(String msgId, Throwable cause) + { + super(msgId, cause); + // TODO Auto-generated constructor stub + } + + /** + * @param msgId String + * @param msgParams Object[] + * @param cause Throwable + */ + public QueryModelException(String msgId, Object[] msgParams, Throwable cause) + { + super(msgId, msgParams, cause); + // TODO Auto-generated constructor stub + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryModelFactory.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryModelFactory.java new file mode 100644 index 0000000000..3db026ede3 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryModelFactory.java @@ -0,0 +1,69 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.alfresco.service.namespace.QName; + +/** + * @author andyh + */ +public interface QueryModelFactory +{ + public Query createQuery(List columns, Source source, Constraint constraint, List orderings); + + public Selector createSelector(QName classQName, String alias); + + public Join createJoin(Source left, Source right, JoinType joinType, Constraint joinCondition); + + public Constraint createConjunction(List constraints); + + public Constraint createDisjunction(List constraints); + + public Constraint createFunctionalConstraint(Function function, Map functionArguments); + + public Column createColumn(Function function, Map functionArguments, String alias); + + public LiteralArgument createLiteralArgument(String name, QName type, Serializable value); + + public Ordering createOrdering(Column column, Order order); + + public ParameterArgument createParameterArgument(String name, String parameterName); + + public PropertyArgument createPropertyArgument(String name, boolean queryable, boolean orderable, String selectorAlias, String propertyName); + + public SelectorArgument createSelectorArgument(String name, String selectorAlias); + + public Function getFunction(String functionName); + + public ListArgument createListArgument(String name, ArrayList arguments); + + public FunctionArgument createFunctionArgument(String name, Function function, Map functionArguments); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryOptions.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryOptions.java new file mode 100644 index 0000000000..35af1048ba --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/QueryOptions.java @@ -0,0 +1,596 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.alfresco.repo.search.MLAnalysisMode; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.LimitBy; +import org.alfresco.service.cmr.search.QueryConsistency; +import org.alfresco.service.cmr.search.QueryParameterDefinition; +import org.alfresco.service.cmr.search.SearchParameters; +import org.alfresco.service.cmr.search.SearchService; +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * The options for a query + * + * @author andyh + */ +public class QueryOptions +{ + public enum Connective + { + AND, OR; + } + + private String query; + + private List stores = new ArrayList(1); + + private int maxItems = -1; + + private int skipCount = 0; + + private Connective defaultFTSConnective = Connective.AND; + + private Connective defaultFTSFieldConnective = Connective.AND; + + private List locales = new ArrayList(1); + + private MLAnalysisMode mlAnalaysisMode = MLAnalysisMode.EXACT_LANGUAGE_AND_ALL; + + private List queryParameterDefinitions = new ArrayList(4); + + private boolean includeInTransactionData = true; + + // By default uses the central config + private int maxPermissionChecks = -1; + + // By default uses the central config + private long maxPermissionCheckTimeMillis = -1; + + private String defaultFieldName = "TEXT"; + + private Boolean useInMemorySort; + + private Integer maxRawResultSetSizeForInMemorySort; + + private boolean excludeTenantFilter = false; + + private boolean isBulkFetchEnabled = true; + + private QueryConsistency queryConsistency = QueryConsistency.DEFAULT; + + private Long sinceTxId; + + private Map queryTemplates = new HashMap(); + + public static QueryOptions create(SearchParameters searchParameters) + { + QueryOptions options = new QueryOptions(searchParameters.getQuery(), null); + options.setIncludeInTransactionData(!searchParameters.excludeDataInTheCurrentTransaction()); + options.setDefaultFTSConnective(searchParameters.getDefaultOperator() == SearchParameters.Operator.OR ? Connective.OR : Connective.AND); + options.setDefaultFTSFieldConnective(searchParameters.getDefaultOperator() == SearchParameters.Operator.OR ? Connective.OR : Connective.AND); + options.setSkipCount(searchParameters.getSkipCount()); + options.setMaxPermissionChecks(searchParameters.getMaxPermissionChecks()); + options.setMaxPermissionCheckTimeMillis(searchParameters.getMaxPermissionCheckTimeMillis()); + options.setDefaultFieldName(searchParameters.getDefaultFieldName()); + if (searchParameters.getLimitBy() == LimitBy.FINAL_SIZE) + { + options.setMaxItems(searchParameters.getLimit()); + } + else + { + options.setMaxItems(searchParameters.getMaxItems()); + } + options.setMlAnalaysisMode(searchParameters.getMlAnalaysisMode()); + options.setLocales(searchParameters.getLocales()); + options.setStores(searchParameters.getStores()); + options.setQueryParameterDefinitions(searchParameters.getQueryParameterDefinitions()); + ///options.setQuery(query); Done on construction. + options.setUseInMemorySort(searchParameters.getUseInMemorySort()); + options.setMaxRawResultSetSizeForInMemorySort(searchParameters.getMaxRawResultSetSizeForInMemorySort()); + options.setBulkFetchEnabled(searchParameters.isBulkFetchEnabled()); + options.setExcludeTenantFilter(searchParameters.getExcludeTenantFilter()); + options.setQueryConsistency(searchParameters.getQueryConsistency()); + options.setSinceTxId(searchParameters.getSinceTxId()); + for(String name : searchParameters.getQueryTemplates().keySet()) + { + String template = searchParameters.getQueryTemplates().get(name); + options.addQueryTemplate(name, template); + } + return options; + } + + + + /** + * Create a CMISQueryOptions instance with the default options other than the query and store ref. The query will be + * run using the locale returned by I18NUtil.getLocale() + * + * @param query - + * the query to run + * @param storeRef - + * the store against which to run the query + */ + public QueryOptions(String query, StoreRef storeRef) + { + this(query, storeRef, I18NUtil.getLocale()); + } + + /** + * Create a CMISQueryOptions instance with the default options other than the query, store ref and locale. + * + * @param query - + * the query to run + * @param storeRef - + * the store against which to run the query + */ + public QueryOptions(String query, StoreRef storeRef, Locale locale) + { + this.query = query; + this.stores.add(storeRef); + this.locales.add(locale); + } + + /** + * Get the query string + * + * @return the query + */ + public String getQuery() + { + return query; + } + + /** + * Set the query string + * + * @param query + * the query to set + */ + public void setQuery(String query) + { + this.query = query; + } + + /** + * Get the list of stores in which to run the query. Only one store is supported at the momentOnly one store is + * supported at the moment + * + * @return the stores + */ + public List getStores() + { + return stores; + } + + /** + * Set the stores against which to run the query. Only one store is supported at the moment. + * + * @param stores + * the stores to set + */ + public void setStores(List stores) + { + this.stores = stores; + } + + /** + * Get the max number of rows for the result set 0 or less is unlimited + * + * @return the maxItems + */ + public int getMaxItems() + { + return maxItems; + } + + /** + * Set the max number of rows for the result set 0 or less is unlimited + * + * @param maxItems + * the maxItems to set + */ + public void setMaxItems(int maxItems) + { + this.maxItems = maxItems; + } + + /** + * Get the skip count - the number of rows to skip at the start of the query. + * + * @return the skipCount + */ + public int getSkipCount() + { + return skipCount; + } + + /** + * Set the skip count - the number of rows to skip at the start of the query. + * + * @param skipCount + * the skipCount to set + */ + public void setSkipCount(int skipCount) + { + this.skipCount = skipCount; + } + + /** + * Get the default connective used when OR and AND are not specified for the FTS contains() function. + * + * @return the defaultFTSConnective + */ + public Connective getDefaultFTSConnective() + { + return defaultFTSConnective; + } + + /** + * Set the default connective used when OR and AND are not specified for the FTS contains() function. + * + * @param defaultFTSConnective + * the defaultFTSConnective to set + */ + public void setDefaultFTSConnective(Connective defaultFTSConnective) + { + this.defaultFTSConnective = defaultFTSConnective; + } + + /** + * As getDefaultFTSConnective() but for field groups + * + * @return the defaultFTSFieldConnective + */ + public Connective getDefaultFTSFieldConnective() + { + return defaultFTSFieldConnective; + } + + /** + * As setDefaultFTSConnective() but for field groups + * + * @param defaultFTSFieldConnective + * the defaultFTSFieldConnective to set + */ + public void setDefaultFTSFieldConnective(Connective defaultFTSFieldConnective) + { + this.defaultFTSFieldConnective = defaultFTSFieldConnective; + } + + /** + * Get the list of locales to use for the query + * + * @return the locales + */ + public List getLocales() + { + return locales; + } + + /** + * sSet the list of locales to use for the query + * + * @param locales + * the locales to set + */ + public void setLocales(List locales) + { + this.locales = locales; + } + + /** + * Get the mode for multi-lingual text analaysis + * + * @return the mlAnalaysisMode + */ + public MLAnalysisMode getMlAnalaysisMode() + { + return mlAnalaysisMode; + } + + /** + * Set the mode for multi-lingual text analaysis + * + * @param mlAnalaysisMode + * the mlAnalaysisMode to set + */ + public void setMlAnalaysisMode(MLAnalysisMode mlAnalaysisMode) + { + this.mlAnalaysisMode = mlAnalaysisMode; + } + + /** + * Get the query parameters + * + * @return the queryParameterDefinitions + */ + public List getQueryParameterDefinitions() + { + return queryParameterDefinitions; + } + + /** + * Set the query parameters + * + * @param queryParameterDefinitions + * the queryParameterDefinitions to set + */ + public void setQueryParameterDefinitions(List queryParameterDefinitions) + { + this.queryParameterDefinitions = queryParameterDefinitions; + } + + /** + * Does the search include any changes made in the current transaction? + * + * @return the includeInTransactionData + */ + public boolean isIncludeInTransactionData() + { + return includeInTransactionData; + } + + /** + * Set to true if the search include any changes made in the current transaction. + * + * @param includeInTransactionData + * the includeInTransactionData to set + */ + public void setIncludeInTransactionData(boolean includeInTransactionData) + { + this.includeInTransactionData = includeInTransactionData; + } + + /** + * @return the timeout in millis for permission checks + */ + public long getMaxPermissionCheckTimeMillis() + { + return maxPermissionCheckTimeMillis; + } + + /** + * @param maxPermissionCheckTimeMillis - + * the timeout in millis for permission checks + */ + public void setMaxPermissionCheckTimeMillis(long maxPermissionCheckTimeMillis) + { + this.maxPermissionCheckTimeMillis = maxPermissionCheckTimeMillis; + } + + /** + * @return the max number of permission checks to carry out + */ + public int getMaxPermissionChecks() + { + return maxPermissionChecks; + } + + /** + * @param maxPermissionChecks - + * the max number of permission checks to carry out + */ + public void setMaxPermissionChecks(int maxPermissionChecks) + { + this.maxPermissionChecks = maxPermissionChecks; + } + + /** + * @return the default field name + */ + public String getDefaultFieldName() + { + return defaultFieldName; + } + + /** + * @param defaultFieldName - the default field name to use + */ + public void setDefaultFieldName(String defaultFieldName) + { + this.defaultFieldName = defaultFieldName; + } + + /** + * @return the useInMemorySort + */ + public Boolean getUseInMemorySort() + { + return useInMemorySort; + } + + /** + * @param useInMemorySort the useInMemorySort to set + */ + public void setUseInMemorySort(Boolean useInMemorySort) + { + this.useInMemorySort = useInMemorySort; + } + + /** + * @return the maxRawResultSetSizeForInMemorySort + */ + public Integer getMaxRawResultSetSizeForInMemorySort() + { + return maxRawResultSetSizeForInMemorySort; + } + + /** + * @param maxRawResultSetSizeForInMemorySort the maxRawResultSetSizeForInMemorySort to set + */ + public void setMaxRawResultSetSizeForInMemorySort(Integer maxRawResultSetSizeForInMemorySort) + { + this.maxRawResultSetSizeForInMemorySort = maxRawResultSetSizeForInMemorySort; + } + + /** + * @return true if bulk fetch is enabled + */ + public boolean isBulkFetchEnabled() + { + return isBulkFetchEnabled; + } + + /** + * @param isBulkFetchEnabled boolean + */ + public void setBulkFetchEnabled(boolean isBulkFetchEnabled) + { + this.isBulkFetchEnabled = isBulkFetchEnabled; + } + + /** + * @return the tenants + */ + public boolean getExcludeTenantFilter() + { + return excludeTenantFilter; + } + + /** + * @param excludeTenantFilter boolean + */ + public void setExcludeTenantFilter(boolean excludeTenantFilter) + { + this.excludeTenantFilter = excludeTenantFilter; + } + + /** + * @return the queryConsistency + */ + public QueryConsistency getQueryConsistency() + { + return queryConsistency; + } + /** + * @param queryConsistency the queryConsistency to set + */ + public void setQueryConsistency(QueryConsistency queryConsistency) + { + this.queryConsistency = queryConsistency; + } + + /** + * @return the sinceTxId + */ + public Long getSinceTxId() + { + return this.sinceTxId; + } + + /** + * @param sinceTxId the sinceTxId to set + */ + public void setSinceTxId(Long sinceTxId) + { + this.sinceTxId = sinceTxId; + } + + /** + * Get the query templates + * + * @return - the query templates + */ + public Map getQueryTemplates() + { + return queryTemplates; + } + + /** + * Add/replace a query template Not all languages support query templates + * + * @param name String + * @param template String + * @return any removed template or null + */ + public String addQueryTemplate(String name, String template) + { + return queryTemplates.put(name, template); + } + + + + /** + * @return SearchParameters + */ + public SearchParameters getAsSearchParmeters() + { + SearchParameters searchParameters = new SearchParameters(); + searchParameters.setDefaultFieldName(this.getDefaultFieldName()); + searchParameters.setDefaultFTSFieldConnective(this.getDefaultFTSFieldConnective() == Connective.OR ? SearchParameters.Operator.OR : SearchParameters.Operator.AND); + searchParameters.setDefaultFTSOperator(this.getDefaultFTSConnective() == Connective.OR ? SearchParameters.Operator.OR : SearchParameters.Operator.AND); + searchParameters.setDefaultOperator(this.getDefaultFTSConnective() == Connective.OR ? SearchParameters.Operator.OR : SearchParameters.Operator.AND); + searchParameters.setLanguage(SearchService.LANGUAGE_FTS_ALFRESCO); + if(this.getMaxItems() > 0) + { + searchParameters.setLimit(this.getMaxItems()); + searchParameters.setLimitBy(LimitBy.FINAL_SIZE); + searchParameters.setMaxItems(this.getMaxItems()); + } + searchParameters.setMaxPermissionChecks(this.getMaxPermissionChecks()); + searchParameters.setMaxPermissionCheckTimeMillis(this.getMaxPermissionCheckTimeMillis()); + searchParameters.setMlAnalaysisMode(this.getMlAnalaysisMode()); + //searchParameters.setNamespace() TODO: Fix + //searchParameters.setPermissionEvaluation() + searchParameters.setQuery(this.getQuery()); + searchParameters.setSkipCount(this.getSkipCount()); + //searchParameters.addAllAttribute() + for(Locale locale : this.getLocales()) + { + searchParameters.addLocale(locale); + } + for(QueryParameterDefinition queryParameterDefinition: this.getQueryParameterDefinitions()) + { + searchParameters.addQueryParameterDefinition(queryParameterDefinition); + } + //searchParameters.addQueryTemplate(name, template) + //searchParameters.addSort() + for(StoreRef storeRef : this.getStores()) + { + searchParameters.addStore(storeRef); + } + //searchParameters.addTextAttribute() + searchParameters.setQueryConsistency(this.getQueryConsistency()); + searchParameters.setSinceTxId(getSinceTxId()); + for(String name : getQueryTemplates().keySet()) + { + String template = getQueryTemplates().get(name); + searchParameters.addQueryTemplate(name, template); + } + + return searchParameters; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Selector.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Selector.java new file mode 100644 index 0000000000..c3bd3c8c3b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Selector.java @@ -0,0 +1,49 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import org.alfresco.service.namespace.QName; + +/** + * @author andyh + * + */ +public interface Selector extends Source +{ + /** + * The qname of the type or aspect to select + * @return QName + */ + public QName getType(); + + /** + * The alias or name for the selector + * This must be unique across all selectors in the query + * + * @return String + */ + public String getAlias(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/SelectorArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/SelectorArgument.java new file mode 100644 index 0000000000..db752d7ba1 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/SelectorArgument.java @@ -0,0 +1,36 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +/** + * @author andyh + * + */ +public interface SelectorArgument extends StaticArgument +{ + public String getSelector(); + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Source.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Source.java new file mode 100644 index 0000000000..28364584c7 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/Source.java @@ -0,0 +1,47 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author andyh + * + */ +public interface Source +{ + public Map getSelectors(); + + public Selector getSelector(String name); + + public List> getSelectorGroups(FunctionEvaluationContext functionContext); + + public JoinType getJoinType(); + + public void setJoinType(JoinType joinType); +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/StaticArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/StaticArgument.java new file mode 100644 index 0000000000..49203ed2a9 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/StaticArgument.java @@ -0,0 +1,35 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel; + +/** + * @author andyh + * + */ +public interface StaticArgument extends Argument +{ + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseArgument.java new file mode 100644 index 0000000000..3b56965d7a --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseArgument.java @@ -0,0 +1,67 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import org.alfresco.repo.search.impl.querymodel.Argument; + +/** + * @author andyh + * + */ +public abstract class BaseArgument implements Argument +{ + private String name; + + private boolean queryable; + + private boolean orderable; + + + public BaseArgument(String name, boolean queryable, boolean orderable) + { + this.name = name; + this.queryable = queryable; + this.orderable = orderable; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Argument#getName() + */ + public String getName() + { + return name; + } + + public boolean isOrderable() + { + return orderable; + } + + public boolean isQueryable() + { + return queryable; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseArgumentDefinition.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseArgumentDefinition.java new file mode 100644 index 0000000000..bac24e9528 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseArgumentDefinition.java @@ -0,0 +1,135 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.service.namespace.QName; + +/** + * @author andyh + */ +public class BaseArgumentDefinition implements ArgumentDefinition +{ + private Multiplicity multiplicity; + + private String name; + + private QName type; + + private boolean mandatory; + + public BaseArgumentDefinition(Multiplicity multiplicity, String name, QName type, boolean mandatory) + { + this.multiplicity = multiplicity; + this.name = name; + this.type = type; + this.mandatory = mandatory; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.ArgumentDefinition#getMutiplicity() + */ + public Multiplicity getMutiplicity() + { + return multiplicity; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.ArgumentDefinition#getName() + */ + public String getName() + { + return name; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.ArgumentDefinition#getType() + */ + public QName getType() + { + return type; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.ArgumentDefinition#isMandatory() + */ + public boolean isMandatory() + { + return mandatory; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseArgumentDefinition["); + builder.append("name=").append(getName()).append(", "); + builder.append("multiplicity=").append(getMutiplicity()).append(", "); + builder.append("mandatory=").append(isMandatory()).append(", "); + builder.append("type=").append(getType()); + builder.append("] "); + return builder.toString(); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final BaseArgumentDefinition other = (BaseArgumentDefinition) obj; + if (name == null) + { + if (other.name != null) + return false; + } + else if (!name.equals(other.name)) + return false; + return true; + } + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseColumn.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseColumn.java new file mode 100644 index 0000000000..0bf1de7805 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseColumn.java @@ -0,0 +1,112 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.Column; +import org.alfresco.repo.search.impl.querymodel.Function; + +/** + * @author andyh + * + */ +public class BaseColumn implements Column +{ + private String alias; + + private Function function; + + private Map functionArguments; + + public BaseColumn(Function function, Map functionArguments, String alias) + { + this.function = function; + this.functionArguments = functionArguments; + this.alias = alias; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Column#getAlias() + */ + public String getAlias() + { + return alias; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.FunctionInvokation#getFunction() + */ + public Function getFunction() + { + return function; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.FunctionInvokation#getFunctionArguments() + */ + public Map getFunctionArguments() + { + return functionArguments; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseColumn["); + builder.append("Alias=").append(getAlias()).append(", "); + builder.append("Function=").append(getFunction()).append(", "); + builder.append("FunctionArguments=").append(getFunctionArguments()); + builder.append("]"); + return builder.toString(); + } + + public boolean isOrderable() + { + for(Argument arg : functionArguments.values()) + { + if(!arg.isOrderable()) + { + return false; + } + } + return true; + } + + public boolean isQueryable() + { + for(Argument arg : functionArguments.values()) + { + if(!arg.isQueryable()) + { + return false; + } + } + return true; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseComparison.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseComparison.java new file mode 100644 index 0000000000..02be173223 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseComparison.java @@ -0,0 +1,249 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionArgument; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.StaticArgument; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Lower; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Upper; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.namespace.QName; + +/** + * @author andyh + */ +public abstract class BaseComparison extends BaseFunction +{ + /** + * Left hand side + */ + public final static String ARG_LHS = "LHS"; + + /** + * Right hand side + */ + public final static String ARG_RHS = "RHS"; + + /** + * Mode: SVP or mode for MVP comparisons + */ + public final static String ARG_MODE = "Mode"; + + /** + * Args + */ + public static LinkedHashMap ARGS; + + private PropertyArgument propertyArgument; + + private StaticArgument staticArgument; + + private FunctionArgument functionArgument; + + private String staticPosition; + + static + { + ARGS = new LinkedHashMap(); + ARGS.put(ARG_LHS, new BaseArgumentDefinition(Multiplicity.ANY, ARG_LHS, DataTypeDefinition.ANY, true)); + ARGS.put(ARG_RHS, new BaseArgumentDefinition(Multiplicity.ANY, ARG_RHS, DataTypeDefinition.ANY, true)); + ARGS.put(ARG_MODE, new BaseArgumentDefinition(Multiplicity.ANY, ARG_MODE, DataTypeDefinition.ANY, true)); + + } + + /** + * @param name String + * @param returnType QName + */ + public BaseComparison(String name, QName returnType, LinkedHashMap argumentDefinitions) + { + super(name, returnType, argumentDefinitions); + } + + public void setPropertyAndStaticArguments(Map functionArgs) + { + Argument lhs = functionArgs.get(ARG_LHS); + Argument rhs = functionArgs.get(ARG_RHS); + + if (lhs instanceof PropertyArgument) + { + if ((rhs instanceof PropertyArgument) || (rhs instanceof FunctionArgument)) + { + throw new QueryModelException("Implicit join is not supported"); + } + else if (rhs instanceof StaticArgument) + { + propertyArgument = (PropertyArgument) lhs; + staticArgument = (StaticArgument) rhs; + staticPosition = ARG_RHS; + } + else + { + throw new QueryModelException("Argument of type " + rhs.getClass().getName() + " is not supported"); + } + } + else if (lhs instanceof FunctionArgument) + { + if ((rhs instanceof PropertyArgument) || (rhs instanceof FunctionArgument)) + { + throw new QueryModelException("Implicit join is not supported"); + } + else if (rhs instanceof StaticArgument) + { + functionArgument = (FunctionArgument) lhs; + staticArgument = (StaticArgument) rhs; + staticPosition = ARG_RHS; + } + else + { + throw new QueryModelException("Argument of type " + rhs.getClass().getName() + " is not supported"); + } + } + else if (rhs instanceof PropertyArgument) + { + if ((lhs instanceof PropertyArgument) || (lhs instanceof FunctionArgument)) + { + throw new QueryModelException("Implicit join is not supported"); + } + else if (lhs instanceof StaticArgument) + { + propertyArgument = (PropertyArgument) rhs; + staticArgument = (StaticArgument) lhs; + staticPosition = ARG_LHS; + } + else + { + throw new QueryModelException("Argument of type " + lhs.getClass().getName() + " is not supported"); + } + } + else if (rhs instanceof FunctionArgument) + { + if ((lhs instanceof PropertyArgument) || (lhs instanceof FunctionArgument)) + { + throw new QueryModelException("Implicit join is not supported"); + } + else if (lhs instanceof StaticArgument) + { + functionArgument = (FunctionArgument) rhs; + staticArgument = (StaticArgument) lhs; + staticPosition = ARG_LHS; + } + else + { + throw new QueryModelException("Argument of type " + lhs.getClass().getName() + " is not supported"); + } + } + else + { + throw new QueryModelException("Equals must have one property argument"); + } + } + + /** + * @return the propertyArgument - there must be a property argument of a function argument + */ + protected PropertyArgument getPropertyArgument() + { + return propertyArgument; + } + + /** + * @return the staticArgument - must be set + */ + protected StaticArgument getStaticArgument() + { + return staticArgument; + } + + /** + * @return the staticPosition + */ + public String getStaticPosition() + { + return staticPosition; + } + + /** + * @return the functionArgument + */ + protected FunctionArgument getFunctionArgument() + { + return functionArgument; + } + + public String getPropertyName() + { + if (propertyArgument != null) + { + return propertyArgument.getPropertyName(); + } + else if (functionArgument != null) + { + String functionName = functionArgument.getFunction().getName(); + if (functionName.equals(Upper.NAME)) + { + Argument arg = functionArgument.getFunctionArguments().get(Upper.ARG_ARG); + if (arg instanceof PropertyArgument) + { + return ((PropertyArgument) arg).getPropertyName(); + } + else + { + throw new QueryModelException("Upper must have a column argument " + arg); + } + } + else if (functionName.equals(Lower.NAME)) + { + Argument arg = functionArgument.getFunctionArguments().get(Lower.ARG_ARG); + if (arg instanceof PropertyArgument) + { + return ((PropertyArgument) arg).getPropertyName(); + } + else + { + throw new QueryModelException("Lower must have a column argument " + arg); + } + } + else + { + throw new QueryModelException("Unsupported function: " + functionName); + } + } + else + { + throw new QueryModelException("A property of function argument must be provided"); + } + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseConjunction.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseConjunction.java new file mode 100644 index 0000000000..f7129fb825 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseConjunction.java @@ -0,0 +1,71 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.util.List; + +import org.alfresco.repo.search.impl.querymodel.Conjunction; +import org.alfresco.repo.search.impl.querymodel.Constraint; + +/** + * @author andyh + * + */ +public class BaseConjunction extends BaseConstraint implements Conjunction +{ + + private List constraints; + + public BaseConjunction(List constraints) + { + this.constraints = constraints; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Conjunction#getConstraints() + */ + public List getConstraints() + { + return constraints; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Constraint#evaluate() + */ + public boolean evaluate() + { + throw new UnsupportedOperationException(); + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseConjunction["); + builder.append("constraints=").append(getConstraints()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseConstraint.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseConstraint.java new file mode 100644 index 0000000000..ab6eb5c7db --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseConstraint.java @@ -0,0 +1,62 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import org.alfresco.repo.search.impl.querymodel.Constraint; + +public abstract class BaseConstraint implements Constraint +{ + + private Occur occur = Occur.DEFAULT; + + private float boost = 1.0f; + + public BaseConstraint() + { + + } + + public Occur getOccur() + { + return occur; + } + + public void setOccur(Occur occur) + { + this.occur = occur; + } + + public float getBoost() + { + return boost; + } + + public void setBoost(float boost) + { + this.boost = boost; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseDisjunction.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseDisjunction.java new file mode 100644 index 0000000000..bb1bf4f765 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseDisjunction.java @@ -0,0 +1,70 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.util.List; + +import org.alfresco.repo.search.impl.querymodel.Constraint; +import org.alfresco.repo.search.impl.querymodel.Disjunction; + +/** + * @author andyh + * + */ +public class BaseDisjunction extends BaseConstraint implements Disjunction +{ + private List constraints; + + public BaseDisjunction(List constraints) + { + this.constraints = constraints; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Disjunction#getConstraints() + */ + public List getConstraints() + { + return constraints; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Constraint#evaluate() + */ + public boolean evaluate() + { + throw new UnsupportedOperationException(); + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseDisjunction["); + builder.append("constraints=").append(getConstraints()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseDynamicArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseDynamicArgument.java new file mode 100644 index 0000000000..3b6a222a9b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseDynamicArgument.java @@ -0,0 +1,47 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import org.alfresco.repo.search.impl.querymodel.DynamicArgument; + +/** + * @author andyh + * + */ +public abstract class BaseDynamicArgument extends BaseArgument implements DynamicArgument +{ + + /** + * @param name String + * @param queryable boolean + * @param orderable boolean + */ + public BaseDynamicArgument(String name, boolean queryable, boolean orderable) + { + super(name, queryable, orderable); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunction.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunction.java new file mode 100644 index 0000000000..71d1c64b4e --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunction.java @@ -0,0 +1,106 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.util.LinkedHashMap; + +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.Function; +import org.alfresco.service.namespace.QName; + +/** + * @author andyh + */ +public abstract class BaseFunction implements Function +{ + + private String name; + + private QName returnType; + + private LinkedHashMap argumentDefinitions; + + public BaseFunction(String name, QName returnType, LinkedHashMap argumentDefinitions) + { + this.name = name; + this.returnType = returnType; + this.argumentDefinitions = argumentDefinitions; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getArgumentDefinitions() + */ + public LinkedHashMap getArgumentDefinitions() + { + return argumentDefinitions; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getName() + */ + public String getName() + { + return name; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getReturnType() + */ + public QName getReturnType() + { + return returnType; + } + + public ArgumentDefinition getArgumentDefinition(String name) + { + ArgumentDefinition definition = argumentDefinitions.get(name); + if (definition != null) + { + return definition; + } + else + { + throw new IllegalArgumentException(name); + } + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseFunction["); + builder.append("Name=" + getName()).append(", "); + builder.append("Return type=" + getReturnType()).append(", "); + builder.append("ArgumentDefinitions=" + getArgumentDefinitions()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunctionArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunctionArgument.java new file mode 100644 index 0000000000..08b1f2c74b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunctionArgument.java @@ -0,0 +1,101 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.Function; +import org.alfresco.repo.search.impl.querymodel.FunctionArgument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; + +/** + * @author andyh + * + */ +public class BaseFunctionArgument extends BaseDynamicArgument implements FunctionArgument +{ + + private Function function; + + private Map arguments; + + public BaseFunctionArgument(String name, Function function, Map arguments) + { + super(name, false, false); + this.function = function; + this.arguments = arguments; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Argument#getValue() + */ + public Serializable getValue(FunctionEvaluationContext context) + { + return function.getValue(arguments, context); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.FunctionInvokation#getFunction() + */ + public Function getFunction() + { + return function; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.FunctionInvokation#getFunctionArguments() + */ + public Map getFunctionArguments() + { + return arguments; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseFunctionArgument["); + builder.append("Name=").append(getName()).append(", "); + builder.append("Function="+getFunction()).append(", "); + builder.append("Arguments="+getFunctionArguments()); + builder.append("]"); + return builder.toString(); + } + + public boolean isQueryable() + { + for(Argument arg : arguments.values()) + { + if(!arg.isQueryable()) + { + return false; + } + } + return true; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunctionalConstraint.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunctionalConstraint.java new file mode 100644 index 0000000000..b706136fa8 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseFunctionalConstraint.java @@ -0,0 +1,83 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.Function; +import org.alfresco.repo.search.impl.querymodel.FunctionalConstraint; + +/** + * @author andyh + * + */ +public class BaseFunctionalConstraint extends BaseConstraint implements FunctionalConstraint +{ + private Function function; + + private Map arguments; + + public BaseFunctionalConstraint(Function function, Map arguments) + { + this.function = function; + this.arguments = arguments; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Constraint#evaluate() + */ + public boolean evaluate() + { + throw new UnsupportedOperationException(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.FunctionInvokation#getFunction() + */ + public Function getFunction() + { + return function; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.FunctionInvokation#getFunctionArguments() + */ + public Map getFunctionArguments() + { + return arguments; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseFunctionalConstraint["); + builder.append("Function="+getFunction()).append(", "); + builder.append("Arguments="+getFunctionArguments()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseJoin.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseJoin.java new file mode 100644 index 0000000000..0e6e1c4b99 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseJoin.java @@ -0,0 +1,256 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.Constraint; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.FunctionalConstraint; +import org.alfresco.repo.search.impl.querymodel.Join; +import org.alfresco.repo.search.impl.querymodel.JoinType; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.Selector; +import org.alfresco.repo.search.impl.querymodel.Source; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Equals; + +/** + * @author andyh + */ +public class BaseJoin implements Join +{ + private Constraint joinConstraint; + + private JoinType joinType; + + private Source left; + + private Source right; + + public BaseJoin(Source left, Source right, JoinType joinType, Constraint joinConstraint) + { + this.left = left; + this.right = right; + this.joinType = joinType; + this.joinConstraint = joinConstraint; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Join#getJoinCondition() + */ + public Constraint getJoinCondition() + { + return joinConstraint; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Join#getJoinType() + */ + public JoinType getJoinType() + { + return joinType; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Join#getLeft() + */ + public Source getLeft() + { + return left; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Join#getRight() + */ + public Source getRight() + { + return right; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseJoin["); + builder.append("Left=" + getLeft()).append(", "); + builder.append("Right=" + getRight()).append(", "); + builder.append("JoinType=" + getJoinType()).append(", "); + builder.append("Condition=" + getJoinCondition()); + builder.append("]"); + return builder.toString(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Source#getSelectorNames() + */ + public Map getSelectors() + { + HashMap answer = new HashMap(); + Map leftSelectors = left.getSelectors(); + for (String selectorName : leftSelectors.keySet()) + { + Selector selector = leftSelectors.get(selectorName); + if (answer.put(selectorName, selector) != null) + { + throw new DuplicateSelectorNameException("There is a duplicate selector name for " + selectorName); + } + } + Map rightSelectors = right.getSelectors(); + for (String selectorName : rightSelectors.keySet()) + { + Selector selector = rightSelectors.get(selectorName); + if (answer.put(selectorName, selector) != null) + { + throw new DuplicateSelectorNameException("There is a duplicate selector name for " + selectorName); + } + } + return answer; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Source#getSelector(java.lang.String) + */ + public Selector getSelector(String name) + { + Map answer = getSelectors(); + return answer.get(name); + } + + public List> getSelectorGroups(FunctionEvaluationContext functionContext) + { + List> answer = new ArrayList>(); + + List> left = getLeft().getSelectorGroups(functionContext); + List> right = getRight().getSelectorGroups(functionContext); + + FunctionalConstraint joinCondition = (FunctionalConstraint) getJoinCondition(); + if (!joinCondition.getFunction().getName().equals(Equals.NAME)) + { + throw new UnsupportedOperationException("Only equi-joins are supported"); + } + + Argument lhs = joinCondition.getFunctionArguments().get(Equals.ARG_LHS); + Argument rhs = joinCondition.getFunctionArguments().get(Equals.ARG_RHS); + + String lhsSelector = null; + String rhsSelector = null; + + if (lhs instanceof PropertyArgument) + { + PropertyArgument propertyArgument = (PropertyArgument) lhs; + String name = propertyArgument.getPropertyName(); + if (functionContext.isObjectId(name)) + { + lhsSelector = propertyArgument.getSelector(); + } + } + + if (rhs instanceof PropertyArgument) + { + PropertyArgument propertyArgument = (PropertyArgument) rhs; + String name = propertyArgument.getPropertyName(); + if (functionContext.isObjectId(name)) + { + rhsSelector = propertyArgument.getSelector(); + } + } + + if ( ((getJoinType() == JoinType.INNER) || (getJoinType() == JoinType.LEFT)) && (lhsSelector != null) && (rhsSelector != null)) + { + + TOADD: for (Set toAddTo : left) + { + if (toAddTo.contains(lhsSelector)) + { + TOMOVE: for (Set toMove : right) + { + if (toMove.contains(rhsSelector)) + { + toAddTo.addAll(toMove); + toMove.clear(); + break TOMOVE; + } + } + break TOADD; + } + if (toAddTo.contains(rhsSelector)) + { + TOMOVE: for (Set toMove : right) + { + if (toMove.contains(lhsSelector)) + { + toAddTo.addAll(toMove); + toMove.clear(); + break TOMOVE; + } + } + break TOADD; + } + } + } + + // remove any empty sets + + for (Set group : left) + { + if (group.size() > 0) + { + answer.add(group); + } + } + for (Set group : right) + { + if (group.size() > 0) + { + answer.add(group); + } + } + + return answer; + } + + @Override + public void setJoinType(JoinType joinType) + { + this.joinType = joinType; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseListArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseListArgument.java new file mode 100644 index 0000000000..0baa8cb05b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseListArgument.java @@ -0,0 +1,97 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.ListArgument; + +/** + * @author andyh + * + */ +public class BaseListArgument extends BaseStaticArgument implements ListArgument +{ + private List arguments; + + /** + * @param name String + */ + public BaseListArgument(String name, List arguments) + { + super(name, false, false); + this.arguments = arguments; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.ListArgument#getArguments() + */ + public List getArguments() + { + return arguments; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Argument#getValue() + */ + public Serializable getValue(FunctionEvaluationContext context) + { + ArrayList answer = new ArrayList(arguments.size()); + for(Argument argument : arguments) + { + Serializable value = argument.getValue(context); + answer.add(value); + } + return answer; + + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseListArgument["); + builder.append("name=").append(getName()).append(", "); + builder.append("values=").append(getArguments()); + builder.append("]"); + return builder.toString(); + } + + public boolean isQueryable() + { + for(Argument arg : arguments) + { + if(!arg.isQueryable()) + { + return false; + } + } + return true; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseLiteralArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseLiteralArgument.java new file mode 100644 index 0000000000..f6156bda40 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseLiteralArgument.java @@ -0,0 +1,78 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.io.Serializable; + +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.LiteralArgument; +import org.alfresco.service.namespace.QName; + +/** + * @author andyh + * + */ +public class BaseLiteralArgument extends BaseStaticArgument implements LiteralArgument +{ + private QName type; + + private Serializable value; + + public BaseLiteralArgument(String name, QName type, Serializable value) + { + super(name, true, false); + this.type = type; + this.value = value; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.LiteralArgument#getValue() + */ + public Serializable getValue(FunctionEvaluationContext context) + { + return value; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.LiteralArgument#getType() + */ + public QName getType() + { + return type; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseLiteralArgument["); + builder.append("name=").append(getName()).append(", "); + builder.append("type=").append(getType()).append(", "); + builder.append("value=").append(getValue(null)).append(", "); + builder.append("]"); + return builder.toString(); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseOrdering.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseOrdering.java new file mode 100644 index 0000000000..f8a196b7a8 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseOrdering.java @@ -0,0 +1,74 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import org.alfresco.repo.search.impl.querymodel.Column; +import org.alfresco.repo.search.impl.querymodel.Order; +import org.alfresco.repo.search.impl.querymodel.Ordering; + +/** + * @author andyh + * + */ +public class BaseOrdering implements Ordering +{ + private Column column; + + private Order order; + + public BaseOrdering(Column column, Order order) + { + this.column = column; + this.order = order; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Ordering#getColumn() + */ + public Column getColumn() + { + return column; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Ordering#getOrder() + */ + public Order getOrder() + { + return order; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseOrdering["); + builder.append("Column=" + getColumn()).append(", "); + builder.append("Order=" + getOrder()); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseParameterArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseParameterArgument.java new file mode 100644 index 0000000000..454f7fcb58 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseParameterArgument.java @@ -0,0 +1,77 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.io.Serializable; + +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.ParameterArgument; + +/** + * @author andyh + * + */ +public class BaseParameterArgument extends BaseStaticArgument implements ParameterArgument +{ + private String parameterName; + + /** + * @param name String + * @param parameterName String + */ + public BaseParameterArgument(String name, String parameterName) + { + super(name, true, false); + this.parameterName = parameterName; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.ParameterArgument#getParameterName() + */ + public String getParameterName() + { + return parameterName; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Argument#getValue() + */ + public Serializable getValue(FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseParameterArgument["); + builder.append("name=").append(getName()).append(", "); + builder.append("parameterName=").append(getParameterName()); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BasePropertyArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BasePropertyArgument.java new file mode 100644 index 0000000000..97c9dd985b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BasePropertyArgument.java @@ -0,0 +1,100 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.io.Serializable; + +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * @author andyh + */ +public class BasePropertyArgument extends BaseDynamicArgument implements PropertyArgument +{ + private String propertyName; + + private String selector; + + /** + * @param name String + * @param queryable boolean + * @param orderable boolean + * @param selector String + * @param propertyName String + */ + public BasePropertyArgument(String name, boolean queryable, boolean orderable, String selector, String propertyName) + { + super(name, queryable, orderable); + this.selector = selector; + this.propertyName = propertyName; + + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.PropertyArgument#getSelector() + */ + public String getSelector() + { + return selector; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.PropertyArgument#getPropertyName() + */ + public String getPropertyName() + { + return propertyName; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Argument#getValue() + */ + public Serializable getValue(FunctionEvaluationContext context) + { + NodeRef nodeRef = context.getNodeRefs().get(getSelector()); + return context.getProperty(nodeRef, getPropertyName()); + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BasePropertyArgument["); + builder.append("name=").append(getName()).append(", "); + builder.append("selector=").append(getSelector()).append(", "); + builder.append("propertName=").append(getPropertyName()).append(", "); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseQuery.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseQuery.java new file mode 100644 index 0000000000..033a39611d --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseQuery.java @@ -0,0 +1,109 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.util.List; + +import org.alfresco.repo.search.impl.querymodel.Column; +import org.alfresco.repo.search.impl.querymodel.Constraint; +import org.alfresco.repo.search.impl.querymodel.Ordering; +import org.alfresco.repo.search.impl.querymodel.Query; +import org.alfresco.repo.search.impl.querymodel.Source; + +/** + * @author andyh + */ +public class BaseQuery implements Query +{ + private Source source; + + private List columns; + + private Constraint constraint; + + private List orderings; + + public BaseQuery(List columns, Source source, Constraint constraint, List orderings) + { + this.columns = columns; + this.source = source; + this.constraint = constraint; + this.orderings = orderings; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Query#getColumns() + */ + public List getColumns() + { + return columns; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Query#getConstraint() + */ + public Constraint getConstraint() + { + return constraint; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Query#getOrderings() + */ + public List getOrderings() + { + return orderings; + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Query#getSource() + */ + public Source getSource() + { + return source; + } + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseQuery[\n"); + builder.append("\tcolumns=").append(getColumns()).append("\n"); + builder.append("\tsource=").append(getSource()).append("\n"); + builder.append("\tconstraint=").append(getConstraint()).append("\n"); + builder.append("\torderings=").append(getOrderings()).append("\n"); + builder.append("]"); + return builder.toString(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseSelector.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseSelector.java new file mode 100644 index 0000000000..5ec0b0db24 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseSelector.java @@ -0,0 +1,126 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.JoinType; +import org.alfresco.repo.search.impl.querymodel.Selector; +import org.alfresco.service.namespace.QName; + +/** + * @author andyh + */ +public class BaseSelector implements Selector +{ + private QName type; + + private String alias; + + private JoinType joinType = JoinType.NONE; + + public BaseSelector(QName type, String alias) + { + this.type = type; + this.alias = alias; + } + + @Override + public String getAlias() + { + return alias; + } + + @Override + public JoinType getJoinType() + { + return joinType; + } + + @Override + public void setJoinType(JoinType joinType) + { + this.joinType = joinType; + } + + @Override + public QName getType() + { + return type; + } + + + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseSelector["); + builder.append("alias=").append(getAlias()).append(", "); + builder.append("type=").append(getType()).append(", "); + builder.append("joinType=").append(getJoinType()); + builder.append("]"); + return builder.toString(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Source#getSelectorNames() + */ + public Map getSelectors() + { + HashMap answer = new HashMap(); + answer.put(getAlias(), this); + return answer; + } + + public Selector getSelector(String name) + { + if (getAlias().equals(name)) + { + return this; + } + else + { + return null; + } + } + + public List> getSelectorGroups(FunctionEvaluationContext functionContext) + { + HashSet set = new HashSet(); + set.add(getAlias()); + List> answer = new ArrayList>(); + answer.add(set); + return answer; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseSelectorArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseSelectorArgument.java new file mode 100644 index 0000000000..ce97bb7646 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseSelectorArgument.java @@ -0,0 +1,81 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import java.io.Serializable; + +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.SelectorArgument; + +/** + * @author andyh + * + */ +public class BaseSelectorArgument extends BaseStaticArgument implements SelectorArgument +{ + + private String selector; + + /** + * @param name String + * @param selector String + */ + public BaseSelectorArgument(String name, String selector) + { + super(name, true, false); + this.selector = selector; + + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.SelectorArgument#getSelector() + */ + public String getSelector() + { + return selector; + } + + + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Argument#getValue() + */ + public Serializable getValue(FunctionEvaluationContext context) + { + return getSelector(); + } + + + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BaseSelectorArgument["); + builder.append("name=").append(getName()).append(", "); + builder.append("selector=").append(getSelector()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseStaticArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseStaticArgument.java new file mode 100644 index 0000000000..4b7fc5cbef --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/BaseStaticArgument.java @@ -0,0 +1,48 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import org.alfresco.repo.search.impl.querymodel.StaticArgument; + +/** + * @author andyh + * + */ +public abstract class BaseStaticArgument extends BaseArgument implements StaticArgument +{ + + /** + * @param name String + * @param queryable boolean + * @param orderable boolean + */ + public BaseStaticArgument(String name, boolean queryable, boolean orderable) + { + super(name, queryable, orderable); + } + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/DuplicateSelectorNameException.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/DuplicateSelectorNameException.java new file mode 100644 index 0000000000..d2688a748b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/DuplicateSelectorNameException.java @@ -0,0 +1,82 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +import org.alfresco.error.AlfrescoRuntimeException; + +/** + * @author andyh + * + */ +public class DuplicateSelectorNameException extends AlfrescoRuntimeException +{ + + /** + * @param msgId String + * @param msgParams Object[] + * @param cause Throwable + */ + public DuplicateSelectorNameException(String msgId, Object[] msgParams, Throwable cause) + { + super(msgId, msgParams, cause); + // TODO Auto-generated constructor stub + } + + /** + * @param msgId String + * @param msgParams Object[] + */ + public DuplicateSelectorNameException(String msgId, Object[] msgParams) + { + super(msgId, msgParams); + // TODO Auto-generated constructor stub + } + + /** + * @param msgId String + * @param cause Throwable + */ + public DuplicateSelectorNameException(String msgId, Throwable cause) + { + super(msgId, cause); + // TODO Auto-generated constructor stub + } + + /** + * @param msgId String + */ + public DuplicateSelectorNameException(String msgId) + { + super(msgId); + // TODO Auto-generated constructor stub + } + + /** + * + */ + private static final long serialVersionUID = 3163974668059624874L; + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/SimpleConstraint.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/SimpleConstraint.java new file mode 100644 index 0000000000..c3dcb3c91a --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/SimpleConstraint.java @@ -0,0 +1,49 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl; + +/** + * @author Andy + * + */ +public class SimpleConstraint extends BaseConstraint +{ + + public SimpleConstraint(Occur occur) + { + super(); + setOccur(occur); + } + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Constraint#evaluate() + */ + @Override + public boolean evaluate() + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Child.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Child.java new file mode 100644 index 0000000000..2f9446a72c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Child.java @@ -0,0 +1,92 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; + +/** + * @author andyh + */ +public class Child extends BaseFunction +{ + public final static String NAME = "Child"; + + public final static String ARG_PARENT = "Parent"; + + public final static String ARG_SELECTOR = "Selector"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_PARENT, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_PARENT, DataTypeDefinition.TEXT, true)); + args.put(ARG_SELECTOR, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_SELECTOR, DataTypeDefinition.TEXT, false)); + } + + public Child() + { + super(NAME, DataTypeDefinition.BOOLEAN, args); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + Argument selectorArgument = args.get(ARG_SELECTOR); + String selectorName = DefaultTypeConverter.INSTANCE.convert(String.class, selectorArgument.getValue(context)); + Argument parentArgument = args.get(ARG_PARENT); + NodeRef parent = DefaultTypeConverter.INSTANCE.convert(NodeRef.class, parentArgument.getValue(context)); + + NodeRef child = context.getNodeRefs().get(selectorName); + + for (ChildAssociationRef car : context.getNodeService().getParentAssocs(child)) + { + if (car.getParentRef().equals(parent)) + { + return Boolean.TRUE; + } + } + return Boolean.FALSE; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Descendant.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Descendant.java new file mode 100644 index 0000000000..bc1709f0b5 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Descendant.java @@ -0,0 +1,75 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +/** + * @author andyh + */ +public class Descendant extends BaseFunction +{ + public final static String NAME = "Descendant"; + + public final static String ARG_ANCESTOR = "Ancestor"; + + public final static String ARG_SELECTOR = "Selector"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_ANCESTOR, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_ANCESTOR, DataTypeDefinition.TEXT, true)); + args.put(ARG_SELECTOR, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_SELECTOR, DataTypeDefinition.TEXT, false)); + } + + public Descendant() + { + super(NAME, DataTypeDefinition.BOOLEAN, args); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Equals.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Equals.java new file mode 100644 index 0000000000..3382632e5f --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Equals.java @@ -0,0 +1,57 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.impl.BaseComparison; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +/** + * @author andyh + * + */ +public class Equals extends BaseComparison +{ + public final static String NAME = "Equals"; + + public Equals() + { + super(NAME, DataTypeDefinition.BOOLEAN, ARGS); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Exists.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Exists.java new file mode 100644 index 0000000000..bb42d1fcad --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Exists.java @@ -0,0 +1,75 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +/** + * @author andyh + */ +public class Exists extends BaseFunction +{ + public final static String NAME = "Exists"; + + public final static String ARG_PROPERTY = "Property"; + + public final static String ARG_NOT = "Not"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_PROPERTY, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_PROPERTY, DataTypeDefinition.ANY, true)); + args.put(ARG_NOT, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_NOT, DataTypeDefinition.BOOLEAN, false)); + } + + public Exists() + { + super(NAME, DataTypeDefinition.BOOLEAN, args); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSFuzzyTerm.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSFuzzyTerm.java new file mode 100644 index 0000000000..9ee05d8b15 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSFuzzyTerm.java @@ -0,0 +1,74 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +public class FTSFuzzyTerm extends BaseFunction +{ + public final static String NAME = "FTSFuzzyTerm"; + + public final static String ARG_TERM = "Term"; + + public final static String ARG_PROPERTY = "Property"; + + public final static String ARG_MIN_SIMILARITY = "MinSimilarity"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_TERM, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_TERM, DataTypeDefinition.ANY, true)); + args.put(ARG_PROPERTY, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_PROPERTY, DataTypeDefinition.ANY, false)); + args.put(ARG_MIN_SIMILARITY, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_MIN_SIMILARITY, DataTypeDefinition.FLOAT, false)); + + } + + public FTSFuzzyTerm() + { + super(NAME, DataTypeDefinition.BOOLEAN, args); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSPhrase.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSPhrase.java new file mode 100644 index 0000000000..b2b3919167 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSPhrase.java @@ -0,0 +1,81 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +/** + * @author andyh + */ +public class FTSPhrase extends BaseFunction +{ + public final static String NAME = "FTSPhrase"; + + public final static String ARG_PHRASE = "Phrase"; + + public final static String ARG_PROPERTY = "Property"; + + public final static String ARG_SLOP = "Slop"; + + public final static String ARG_TOKENISATION_MODE = "TokenisationMode"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_PHRASE, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_PHRASE, DataTypeDefinition.ANY, true)); + args.put(ARG_PROPERTY, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_PROPERTY, DataTypeDefinition.ANY, false)); + args.put(ARG_SLOP, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_SLOP, DataTypeDefinition.INT, false)); + args.put(ARG_TOKENISATION_MODE, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, false)); + } + + public FTSPhrase() + { + super(NAME, DataTypeDefinition.BOOLEAN, args); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSPrefixTerm.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSPrefixTerm.java new file mode 100644 index 0000000000..97d6d66690 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSPrefixTerm.java @@ -0,0 +1,71 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +public class FTSPrefixTerm extends BaseFunction +{ + public final static String NAME = "FTSPrefixTerm"; + + public final static String ARG_TERM = "Term"; + + public final static String ARG_PROPERTY = "Property"; + + public static LinkedHashMap args; + + public final static String ARG_TOKENISATION_MODE = "TokenisationMode"; + + static + { + args = new LinkedHashMap(); + args.put(ARG_TERM, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_TERM, DataTypeDefinition.ANY, true)); + args.put(ARG_PROPERTY, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_PROPERTY, DataTypeDefinition.ANY, false)); + } + + public FTSPrefixTerm() + { + super(NAME, DataTypeDefinition.BOOLEAN, args); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSProximity.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSProximity.java new file mode 100644 index 0000000000..0f3fbee3de --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSProximity.java @@ -0,0 +1,72 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +public class FTSProximity extends BaseFunction +{ + public final static String NAME = "FTSProximity"; + + public final static String ARG_FIRST = "First"; + + public final static String ARG_LAST = "Last"; + + public final static String ARG_PROPERTY = "Property"; + + public final static String ARG_SLOP = "Slop"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_FIRST, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_FIRST, DataTypeDefinition.ANY, true)); + args.put(ARG_LAST, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_LAST, DataTypeDefinition.ANY, true)); + args.put(ARG_PROPERTY, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_PROPERTY, DataTypeDefinition.ANY, false)); + args.put(ARG_SLOP, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_SLOP, DataTypeDefinition.INT, false)); + } + + public FTSProximity() + { + super(NAME, DataTypeDefinition.BOOLEAN, args); + } + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSRange.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSRange.java new file mode 100644 index 0000000000..95e8407630 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSRange.java @@ -0,0 +1,77 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +public class FTSRange extends BaseFunction +{ + public final static String NAME = "FTSRange"; + + public final static String ARG_FROM_INC = "FromInc"; + + public final static String ARG_FROM = "From"; + + public final static String ARG_TO = "To"; + + public final static String ARG_TO_INC = "ToInc"; + + public final static String ARG_PROPERTY = "Property"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_FROM_INC, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_FROM_INC, DataTypeDefinition.BOOLEAN, true)); + args.put(ARG_FROM, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_FROM, DataTypeDefinition.TEXT, true)); + args.put(ARG_TO, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_TO, DataTypeDefinition.TEXT, true)); + args.put(ARG_TO_INC, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_TO_INC, DataTypeDefinition.BOOLEAN, true)); + args.put(ARG_PROPERTY, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_PROPERTY, DataTypeDefinition.ANY, false)); + } + + public FTSRange() + { + super(NAME, DataTypeDefinition.BOOLEAN, args); + } + + + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSTerm.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSTerm.java new file mode 100644 index 0000000000..f1cd86691e --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSTerm.java @@ -0,0 +1,77 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +/** + * @author andyh + * + */ +public class FTSTerm extends BaseFunction +{ + public final static String NAME = "FTSTerm"; + + public final static String ARG_TERM = "Term"; + + public final static String ARG_PROPERTY = "Property"; + + public final static String ARG_TOKENISATION_MODE = "TokenisationMode"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_TERM, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_TERM, DataTypeDefinition.ANY, true)); + args.put(ARG_PROPERTY, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_PROPERTY, DataTypeDefinition.ANY, false)); + args.put(ARG_TOKENISATION_MODE, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_TOKENISATION_MODE, DataTypeDefinition.ANY, false)); + } + + public FTSTerm() + { + super(NAME, DataTypeDefinition.BOOLEAN, args); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSWildTerm.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSWildTerm.java new file mode 100644 index 0000000000..8a93cb4187 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSWildTerm.java @@ -0,0 +1,71 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +public class FTSWildTerm extends BaseFunction +{ + public final static String NAME = "FTSWildTerm"; + + public final static String ARG_TERM = "Term"; + + public final static String ARG_PROPERTY = "Property"; + + public final static String ARG_TOKENISATION_MODE = "TokenisationMode"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_TERM, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_TERM, DataTypeDefinition.ANY, true)); + args.put(ARG_PROPERTY, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_PROPERTY, DataTypeDefinition.ANY, false)); + } + + public FTSWildTerm() + { + super(NAME, DataTypeDefinition.BOOLEAN, args); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/GreaterThan.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/GreaterThan.java new file mode 100644 index 0000000000..05281d8793 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/GreaterThan.java @@ -0,0 +1,57 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.impl.BaseComparison; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +/** + * @author andyh + * + */ +public class GreaterThan extends BaseComparison +{ + public final static String NAME = "GreaterThan"; + + public GreaterThan() + { + super(NAME, DataTypeDefinition.BOOLEAN, ARGS); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/GreaterThanOrEquals.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/GreaterThanOrEquals.java new file mode 100644 index 0000000000..102e593c12 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/GreaterThanOrEquals.java @@ -0,0 +1,57 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.impl.BaseComparison; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +/** + * @author andyh + * + */ +public class GreaterThanOrEquals extends BaseComparison +{ + public final static String NAME = "GreaterThanOrEquals"; + + public GreaterThanOrEquals() + { + super(NAME, DataTypeDefinition.BOOLEAN, ARGS); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/In.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/In.java new file mode 100644 index 0000000000..e52b0860fd --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/In.java @@ -0,0 +1,80 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +/** + * @author andyh + * + */ +public class In extends BaseFunction +{ + public final static String NAME = "In"; + + public final static String ARG_PROPERTY = "Property"; + + public final static String ARG_LIST = "List"; + + public final static String ARG_NOT = "Not"; + + public final static String ARG_MODE = "Mode"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_MODE, new BaseArgumentDefinition(Multiplicity.ANY, ARG_MODE, DataTypeDefinition.ANY, true)); + args.put(ARG_PROPERTY, new BaseArgumentDefinition(Multiplicity.ANY, ARG_PROPERTY, DataTypeDefinition.ANY, true)); + args.put(ARG_LIST, new BaseArgumentDefinition(Multiplicity.ANY, ARG_LIST, DataTypeDefinition.ANY, true)); + args.put(ARG_NOT, new BaseArgumentDefinition(Multiplicity.ANY, ARG_NOT, DataTypeDefinition.ANY, false)); + } + + public In() + { + super(NAME, DataTypeDefinition.BOOLEAN, args); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/LessThan.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/LessThan.java new file mode 100644 index 0000000000..698d4d639f --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/LessThan.java @@ -0,0 +1,58 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.impl.BaseComparison; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +/** + * @author andyh + */ +public class LessThan extends BaseComparison +{ + public final static String NAME = "LessThan"; + + public LessThan() + { + super(NAME, DataTypeDefinition.BOOLEAN, ARGS); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/LessThanOrEquals.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/LessThanOrEquals.java new file mode 100644 index 0000000000..a05b467809 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/LessThanOrEquals.java @@ -0,0 +1,58 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.impl.BaseComparison; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +/** + * @author andyh + */ +public class LessThanOrEquals extends BaseComparison +{ + public final static String NAME = "LessThanOrEquals"; + + public LessThanOrEquals() + { + super(NAME, DataTypeDefinition.BOOLEAN, ARGS); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Like.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Like.java new file mode 100644 index 0000000000..c7a779e0b4 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Like.java @@ -0,0 +1,78 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +/** + * @author andyh + */ +public class Like extends BaseFunction +{ + public final static String NAME = "Like"; + + public final static String ARG_PROPERTY = "Property"; + + public final static String ARG_EXP = "Exp"; + + public final static String ARG_NOT = "Not"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_PROPERTY, new BaseArgumentDefinition(Multiplicity.ANY, ARG_PROPERTY, DataTypeDefinition.ANY, true)); + args.put(ARG_EXP, new BaseArgumentDefinition(Multiplicity.ANY, ARG_EXP, DataTypeDefinition.TEXT, true)); + args.put(ARG_NOT, new BaseArgumentDefinition(Multiplicity.ANY, ARG_NOT, DataTypeDefinition.BOOLEAN, false)); + } + + public Like() + { + super(NAME, DataTypeDefinition.BOOLEAN, args); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Lower.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Lower.java new file mode 100644 index 0000000000..dc6dd42c15 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Lower.java @@ -0,0 +1,76 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; + +/** + * @author andyh + */ +public class Lower extends BaseFunction +{ + public final static String NAME = "Lower"; + + public final static String ARG_ARG = "Arg"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_ARG, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_ARG, DataTypeDefinition.ANY, true)); + } + + public Lower() + { + super(NAME, DataTypeDefinition.TEXT, args); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + Argument arg = args.get(ARG_ARG); + Serializable value = arg.getValue(context); + String stringValue = DefaultTypeConverter.INSTANCE.convert(String.class, value); + return stringValue.toLowerCase(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/NotEquals.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/NotEquals.java new file mode 100644 index 0000000000..c8cd6bcf4e --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/NotEquals.java @@ -0,0 +1,58 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.impl.BaseComparison; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +/** + * @author andyh + */ +public class NotEquals extends BaseComparison +{ + public final static String NAME = "NotEquals"; + + public NotEquals() + { + super(NAME, DataTypeDefinition.BOOLEAN, ARGS); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/PropertyAccessor.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/PropertyAccessor.java new file mode 100644 index 0000000000..661dcb94d2 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/PropertyAccessor.java @@ -0,0 +1,79 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +/** + * @author andyh + */ +public class PropertyAccessor extends BaseFunction +{ + public final static String NAME = "PropertyAccessor"; + + public final static String ARG_PROPERTY = "Property"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_PROPERTY, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_PROPERTY, DataTypeDefinition.ANY, true)); + } + + public PropertyAccessor() + { + super(NAME, DataTypeDefinition.ANY, args); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + Argument arg = args.get(ARG_PROPERTY); + if(!(arg instanceof PropertyArgument)) + { + throw new QueryModelException("Function "+NAME+" requires a property argument"); + } + return arg.getValue(context); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Score.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Score.java new file mode 100644 index 0000000000..dcc7002483 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Score.java @@ -0,0 +1,80 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +/** + * @author andyh + */ +public class Score extends BaseFunction +{ + public final static String NAME = "Score"; + + public final static String ARG_QUALIFIER = "Qualifier"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_QUALIFIER, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_QUALIFIER, DataTypeDefinition.ANY, true)); + } + + public Score() + { + super(NAME, DataTypeDefinition.FLOAT, args); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + Argument qualifier = args.get(ARG_QUALIFIER); + if(qualifier != null) + { + return context.getScores().get(qualifier.getValue(context)); + } + else + { + return context.getScore(); + } + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Upper.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Upper.java new file mode 100644 index 0000000000..0b70087025 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/functions/Upper.java @@ -0,0 +1,76 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; + +/** + * @author andyh + */ +public class Upper extends BaseFunction +{ + public final static String NAME = "Upper"; + + public final static String ARG_ARG = "Arg"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_ARG, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_ARG, DataTypeDefinition.ANY, true)); + } + + public Upper() + { + super(NAME, DataTypeDefinition.TEXT, args); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.Function#getValue(java.util.Set) + */ + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + Argument arg = args.get(ARG_ARG); + Serializable value = arg.getValue(context); + String stringValue = DefaultTypeConverter.INSTANCE.convert(String.class, value); + return stringValue.toUpperCase(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneColumn.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneColumn.java new file mode 100644 index 0000000000..4ef1a8ee10 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneColumn.java @@ -0,0 +1,50 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.Function; +import org.alfresco.repo.search.impl.querymodel.impl.BaseColumn; + +/** + * @author andyh + * + */ +public class LuceneColumn extends BaseColumn +{ + + /** + * @param function Function + * @param alias String + */ + public LuceneColumn(Function function, Map functionArguments, String alias) + { + super(function, functionArguments, alias); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneConjunction.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneConjunction.java new file mode 100644 index 0000000000..9f333ebcc8 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneConjunction.java @@ -0,0 +1,106 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserExpressionAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.Constraint; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.impl.BaseConjunction; + +/** + * @author andyh + */ +public class LuceneConjunction extends BaseConjunction implements LuceneQueryBuilderComponent +{ + + /** + */ + public LuceneConjunction(List constraints) + { + super(constraints); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(java.lang.String, + * java.util.Map, org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext, + * org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + + LuceneQueryParserExpressionAdaptor expressionAdaptor = luceneContext.getLuceneQueryParserAdaptor().getExpressionAdaptor(); + boolean must = false; + boolean must_not = false; + for (Constraint constraint : getConstraints()) + { + if (constraint instanceof LuceneQueryBuilderComponent) + { + @SuppressWarnings("unchecked") + LuceneQueryBuilderComponent luceneQueryBuilderComponent = (LuceneQueryBuilderComponent) constraint; + Q constraintQuery = luceneQueryBuilderComponent.addComponent(selectors, functionArgs, luceneContext, functionContext); + + if (constraintQuery != null) + { + switch (constraint.getOccur()) + { + case DEFAULT: + case MANDATORY: + expressionAdaptor.addRequired(constraintQuery, constraint.getBoost()); + must = true; + break; + case OPTIONAL: + expressionAdaptor.addOptional(constraintQuery, constraint.getBoost()); + break; + case EXCLUDE: + expressionAdaptor.addExcluded(constraintQuery, constraint.getBoost()); + must_not = true; + break; + } + + } + } + else + { + throw new UnsupportedOperationException(); + } + if(!must && must_not) + { + expressionAdaptor.addRequired(luceneContext.getLuceneQueryParserAdaptor().getMatchAllNodesQuery()); + } + } + return expressionAdaptor.getQuery(); + + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneDisjunction.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneDisjunction.java new file mode 100644 index 0000000000..25722570b5 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneDisjunction.java @@ -0,0 +1,100 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserExpressionAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.Constraint; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.impl.BaseDisjunction; +import org.alfresco.util.Pair; + +/** + * @author andyh + */ +public class LuceneDisjunction extends BaseDisjunction implements LuceneQueryBuilderComponent +{ + + /** + */ + public LuceneDisjunction(List constraints) + { + super(constraints); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(java.lang.String, + * java.util.Map, org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext, + * org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserExpressionAdaptor expressionBuilder = luceneContext.getLuceneQueryParserAdaptor().getExpressionAdaptor(); + ArrayList> queriestoDisjoin = new ArrayList<>(); + for (Constraint constraint : getConstraints()) + { + if (constraint instanceof LuceneQueryBuilderComponent) + { + @SuppressWarnings("unchecked") + LuceneQueryBuilderComponent luceneQueryBuilderComponent = (LuceneQueryBuilderComponent) constraint; + Q constraintQuery = luceneQueryBuilderComponent.addComponent(selectors, functionArgs, luceneContext, functionContext); + queriestoDisjoin.add(new Pair(constraint, constraintQuery)); + if (constraintQuery != null) + { + switch (constraint.getOccur()) + { + case DEFAULT: + case MANDATORY: + case OPTIONAL: + expressionBuilder.addOptional(constraintQuery, constraint.getBoost()); + break; + case EXCLUDE: + LuceneQueryParserExpressionAdaptor subExpressionBuilder = luceneContext.getLuceneQueryParserAdaptor().getExpressionAdaptor(); + subExpressionBuilder.addRequired(luceneContext.getLuceneQueryParserAdaptor().getMatchAllNodesQuery()); + subExpressionBuilder.addExcluded(constraintQuery); + expressionBuilder.addOptional(subExpressionBuilder.getQuery(), constraint.getBoost()); + break; + } + } + } + else + { + throw new UnsupportedOperationException(); + } + } + return expressionBuilder.getQuery(); + + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneFunctionArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneFunctionArgument.java new file mode 100644 index 0000000000..c2bec8bdd0 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneFunctionArgument.java @@ -0,0 +1,50 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.Function; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunctionArgument; + +/** + * @author andyh + * + */ +public class LuceneFunctionArgument extends BaseFunctionArgument +{ + + /** + * @param name String + * @param function Function + */ + public LuceneFunctionArgument(String name, Function function, Map arguments) + { + super(name, function, arguments); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneFunctionalConstraint.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneFunctionalConstraint.java new file mode 100644 index 0000000000..7892f29033 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneFunctionalConstraint.java @@ -0,0 +1,73 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.Function; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunctionalConstraint; + +/** + * @author andyh + * + */ +public class LuceneFunctionalConstraint extends BaseFunctionalConstraint implements LuceneQueryBuilderComponent +{ + + /** + * @param function Function + */ + public LuceneFunctionalConstraint(Function function, Map arguments) + { + super(function, arguments); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) throws E + { + Function function = getFunction(); + if(function != null) + { + if(function instanceof LuceneQueryBuilderComponent) + { + @SuppressWarnings("unchecked") + LuceneQueryBuilderComponent luceneQueryBuilderComponent = (LuceneQueryBuilderComponent)function; + return luceneQueryBuilderComponent.addComponent(selectors, getFunctionArguments(), luceneContext, functionContext); + } + else + { + throw new UnsupportedOperationException(); + } + } + return null; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneJoin.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneJoin.java new file mode 100644 index 0000000000..7afd642079 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneJoin.java @@ -0,0 +1,52 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import org.alfresco.repo.search.impl.querymodel.Constraint; +import org.alfresco.repo.search.impl.querymodel.JoinType; +import org.alfresco.repo.search.impl.querymodel.Source; +import org.alfresco.repo.search.impl.querymodel.impl.BaseJoin; + +/** + * @author andyh + * + */ +public class LuceneJoin extends BaseJoin +{ + + /** + * @param left Source + * @param right Source + * @param joinType JoinType + * @param joinConstraint Constraint + */ + public LuceneJoin(Source left, Source right, JoinType joinType, Constraint joinConstraint) + { + super(left, right, joinType, joinConstraint); + // TODO Auto-generated constructor stub + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneListArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneListArgument.java new file mode 100644 index 0000000000..07de2bac27 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneListArgument.java @@ -0,0 +1,49 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import java.util.List; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.impl.BaseListArgument; + +/** + * @author andyh + * + */ +public class LuceneListArgument extends BaseListArgument +{ + + /** + * @param name String + */ + public LuceneListArgument(String name, List arguments) + { + super(name, arguments); + // TODO Auto-generated constructor stub + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneLiteralArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneLiteralArgument.java new file mode 100644 index 0000000000..9820b6dcbc --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneLiteralArgument.java @@ -0,0 +1,50 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import java.io.Serializable; + +import org.alfresco.repo.search.impl.querymodel.impl.BaseLiteralArgument; +import org.alfresco.service.namespace.QName; + +/** + * @author andyh + * + */ +public class LuceneLiteralArgument extends BaseLiteralArgument +{ + + /** + * @param name String + * @param type QName + * @param value Serializable + */ + public LuceneLiteralArgument(String name, QName type, Serializable value) + { + super(name, type, value); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneOrdering.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneOrdering.java new file mode 100644 index 0000000000..3b186c97a1 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneOrdering.java @@ -0,0 +1,49 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import org.alfresco.repo.search.impl.querymodel.Column; +import org.alfresco.repo.search.impl.querymodel.Order; +import org.alfresco.repo.search.impl.querymodel.impl.BaseOrdering; + +/** + * @author andyh + * + */ +public class LuceneOrdering extends BaseOrdering +{ + + /** + * @param column Column + * @param order Order + */ + public LuceneOrdering(Column column, Order order) + { + super(column, order); + // TODO Auto-generated constructor stub + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneParameterArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneParameterArgument.java new file mode 100644 index 0000000000..82d53e5909 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneParameterArgument.java @@ -0,0 +1,47 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import org.alfresco.repo.search.impl.querymodel.impl.BaseParameterArgument; + +/** + * @author andyh + * + */ +public class LuceneParameterArgument extends BaseParameterArgument +{ + + /** + * @param name String + * @param parameterName String + */ + public LuceneParameterArgument(String name, String parameterName) + { + super(name, parameterName); + // TODO Auto-generated constructor stub + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LucenePropertyArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LucenePropertyArgument.java new file mode 100644 index 0000000000..975069663f --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LucenePropertyArgument.java @@ -0,0 +1,49 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import org.alfresco.repo.search.impl.querymodel.impl.BasePropertyArgument; + +/** + * @author andyh + * + */ +public class LucenePropertyArgument extends BasePropertyArgument +{ + + /** + * @param name String + * @param queryable boolean + * @param orderable boolean + * @param selector String + * @param propertyName String + */ + public LucenePropertyArgument(String name, boolean queryable, boolean orderable, String selector, String propertyName) + { + super(name, queryable, orderable, selector, propertyName); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQuery.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQuery.java new file mode 100644 index 0000000000..2ce6973cf1 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQuery.java @@ -0,0 +1,198 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserExpressionAdaptor; +import org.alfresco.repo.search.impl.querymodel.Column; +import org.alfresco.repo.search.impl.querymodel.Constraint; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Order; +import org.alfresco.repo.search.impl.querymodel.Ordering; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.Selector; +import org.alfresco.repo.search.impl.querymodel.Source; +import org.alfresco.repo.search.impl.querymodel.impl.BaseQuery; +import org.alfresco.repo.search.impl.querymodel.impl.SimpleConstraint; +import org.alfresco.repo.search.impl.querymodel.impl.functions.PropertyAccessor; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Score; +import org.alfresco.service.cmr.search.SearchParameters.SortDefinition; +import org.alfresco.service.cmr.search.SearchParameters.SortDefinition.SortType; +import org.alfresco.util.Pair; + +/** + * @author andyh + */ +public class LuceneQuery extends BaseQuery implements LuceneQueryBuilder +{ + + /** + * @param source Source + * @param constraint Constraint + */ + public LuceneQuery(List columns, Source source, Constraint constraint, List orderings) + { + super(columns, source, constraint, orderings); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilder#buildQuery() + */ + public Q buildQuery(Set selectors, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) throws E + { + LuceneQueryParserExpressionAdaptor expressionBuilder = luceneContext.getLuceneQueryParserAdaptor().getExpressionAdaptor(); + + boolean must = false; + boolean must_not = false; + + ArrayList> queriestoConjoin = new ArrayList<>(); + + if (selectors != null) + { + for (String selector : selectors) + { + Selector current = getSource().getSelector(selector); + if (current instanceof LuceneQueryBuilderComponent) + { + @SuppressWarnings("unchecked") + LuceneQueryBuilderComponent luceneQueryBuilderComponent = (LuceneQueryBuilderComponent) current; + Q selectorQuery = luceneQueryBuilderComponent.addComponent(selectors, null, luceneContext, functionContext); + queriestoConjoin.add(new Pair(new SimpleConstraint(org.alfresco.repo.search.impl.querymodel.Constraint.Occur.MANDATORY), selectorQuery)); + if (selectorQuery != null) + { + expressionBuilder.addRequired(selectorQuery); + must = true; + } + } + else + { + throw new UnsupportedOperationException(); + } + } + } + + Constraint constraint = getConstraint(); + if (constraint != null) + { + if (constraint instanceof LuceneQueryBuilderComponent) + { + @SuppressWarnings("unchecked") + LuceneQueryBuilderComponent luceneQueryBuilderComponent = (LuceneQueryBuilderComponent) constraint; + Q constraintQuery = luceneQueryBuilderComponent.addComponent(selectors, null, luceneContext, functionContext); + queriestoConjoin.add(new Pair(constraint, constraintQuery)); + + if (constraintQuery != null) + { + switch (constraint.getOccur()) + { + case DEFAULT: + case MANDATORY: + expressionBuilder.addRequired(constraintQuery, constraint.getBoost()); + must = true; + break; + case OPTIONAL: + expressionBuilder.addOptional(constraintQuery, constraint.getBoost()); + break; + case EXCLUDE: + expressionBuilder.addExcluded(constraintQuery, constraint.getBoost()); + must_not = true; + break; + } + } + } + else + { + throw new UnsupportedOperationException(); + } + } + + if (!must && must_not) + { + expressionBuilder.addRequired(luceneContext.getLuceneQueryParserAdaptor().getMatchAllNodesQuery()); + } + + return expressionBuilder.getQuery(); + + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilder#buildSort(java.lang.String, + * org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext, + * org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext) + */ + public S buildSort(Set selectors, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) throws E + { + if ((getOrderings() == null) || (getOrderings().size() == 0)) + { + return null; + } + + return luceneContext.getLuceneQueryParserAdaptor().buildSort(getOrderings(), functionContext); + } + + public List buildSortDefinitions(Set selectors, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + { + if ((getOrderings() == null) || (getOrderings().size() == 0)) + { + return Collections.emptyList(); + } + + ArrayList definitions = new ArrayList(getOrderings().size()); + + for (Ordering ordering : getOrderings()) + { + if (ordering.getColumn().getFunction().getName().equals(PropertyAccessor.NAME)) + { + PropertyArgument property = (PropertyArgument) ordering.getColumn().getFunctionArguments().get(PropertyAccessor.ARG_PROPERTY); + + if (property == null) + { + throw new IllegalStateException(); + } + + String propertyName = property.getPropertyName(); + + String fieldName = functionContext.getLuceneFieldName(propertyName); + + definitions.add(new SortDefinition(SortType.FIELD, fieldName, ordering.getOrder() == Order.ASCENDING)); + } + else if (ordering.getColumn().getFunction().getName().equals(Score.NAME)) + { + definitions.add(new SortDefinition(SortType.SCORE, null, ordering.getOrder() == Order.ASCENDING)); + } + } + + return definitions; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilder.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilder.java new file mode 100644 index 0000000000..c0f3e4946a --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilder.java @@ -0,0 +1,66 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import java.util.List; +import java.util.Set; + +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.service.cmr.search.SearchParameters.SortDefinition; + +/** + * @author andyh + * + * @param the query type used by the query engine implementation + * @param the sort type used by the query engine implementation + * @param the exception it throws + * + */ +public interface LuceneQueryBuilder +{ + /** + * Build the matching lucene query + * @param functionContext FunctionEvaluationContext + * @return - the query + * @throws E + */ + public Q buildQuery(Set selectors, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) throws E; + + /** + * Build the matching lucene sort + * @param functionContext FunctionEvaluationContext + * @return - the sort spec + * @throws E + */ + public S buildSort(Set selectors, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) throws E; + + /** + * Build a sort definition for a sorted result set wrapper + * @param functionContext FunctionEvaluationContext + */ + public List buildSortDefinitions(Set selectors, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext); + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderComponent.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderComponent.java new file mode 100644 index 0000000000..bb3683d969 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderComponent.java @@ -0,0 +1,46 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; + +/** + * @author andyh + */ +public interface LuceneQueryBuilderComponent +{ + /** + * Generate the lucene query from the query component + * @param functionContext FunctionEvaluationContext + * @return - the lucene query fragment for this component + * @throws E + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) throws E; +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderContext.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderContext.java new file mode 100644 index 0000000000..65b37de379 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderContext.java @@ -0,0 +1,48 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.service.namespace.NamespacePrefixResolver; + +/** + * @author Andy + * + */ +public interface LuceneQueryBuilderContext +{ + + /** + * @return - the parser + */ + public abstract LuceneQueryParserAdaptor getLuceneQueryParserAdaptor(); + + /** + * @return - the namespace prefix resolver + */ + public abstract NamespacePrefixResolver getNamespacePrefixResolver(); + +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryModelFactory.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryModelFactory.java new file mode 100644 index 0000000000..fb8385d12b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryModelFactory.java @@ -0,0 +1,318 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.Column; +import org.alfresco.repo.search.impl.querymodel.Constraint; +import org.alfresco.repo.search.impl.querymodel.Function; +import org.alfresco.repo.search.impl.querymodel.FunctionArgument; +import org.alfresco.repo.search.impl.querymodel.Join; +import org.alfresco.repo.search.impl.querymodel.JoinType; +import org.alfresco.repo.search.impl.querymodel.ListArgument; +import org.alfresco.repo.search.impl.querymodel.LiteralArgument; +import org.alfresco.repo.search.impl.querymodel.Order; +import org.alfresco.repo.search.impl.querymodel.Ordering; +import org.alfresco.repo.search.impl.querymodel.ParameterArgument; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.Query; +import org.alfresco.repo.search.impl.querymodel.QueryModelFactory; +import org.alfresco.repo.search.impl.querymodel.Selector; +import org.alfresco.repo.search.impl.querymodel.SelectorArgument; +import org.alfresco.repo.search.impl.querymodel.Source; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Child; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Descendant; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Equals; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Exists; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSFuzzyTerm; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSPhrase; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSPrefixTerm; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSProximity; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSRange; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSTerm; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSWildTerm; +import org.alfresco.repo.search.impl.querymodel.impl.functions.GreaterThan; +import org.alfresco.repo.search.impl.querymodel.impl.functions.GreaterThanOrEquals; +import org.alfresco.repo.search.impl.querymodel.impl.functions.In; +import org.alfresco.repo.search.impl.querymodel.impl.functions.LessThan; +import org.alfresco.repo.search.impl.querymodel.impl.functions.LessThanOrEquals; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Like; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Lower; +import org.alfresco.repo.search.impl.querymodel.impl.functions.NotEquals; +import org.alfresco.repo.search.impl.querymodel.impl.functions.PropertyAccessor; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Score; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Upper; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneChild; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneDescendant; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneEquals; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneExists; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneFTSFuzzyTerm; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneFTSPhrase; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneFTSPrefixTerm; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneFTSProximity; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneFTSRange; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneFTSTerm; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneFTSWildTerm; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneGreaterThan; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneGreaterThanOrEquals; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneIn; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneLessThan; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneLessThanOrEquals; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneLike; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneLower; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneNotEquals; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LucenePropertyAccessor; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneScore; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneUpper; +import org.alfresco.service.namespace.QName; + +/** + * @author andyh + */ +public class LuceneQueryModelFactory implements QueryModelFactory +{ + private HashMap functions = new HashMap(); + + /** + * Default lucene query model factory and functions + */ + public LuceneQueryModelFactory() + { + functions.put(Equals.NAME, new LuceneEquals()); + functions.put(PropertyAccessor.NAME, new LucenePropertyAccessor()); + functions.put(Score.NAME, new LuceneScore()); + functions.put(Upper.NAME, new LuceneUpper()); + functions.put(Lower.NAME, new LuceneLower()); + + functions.put(NotEquals.NAME, new LuceneNotEquals()); + functions.put(LessThan.NAME, new LuceneLessThan()); + functions.put(LessThanOrEquals.NAME, new LuceneLessThanOrEquals()); + functions.put(GreaterThan.NAME, new LuceneGreaterThan()); + functions.put(GreaterThanOrEquals.NAME, new LuceneGreaterThanOrEquals()); + + functions.put(In.NAME, new LuceneIn()); + functions.put(Like.NAME, new LuceneLike()); + functions.put(Exists.NAME, new LuceneExists()); + + functions.put(Child.NAME, new LuceneChild()); + functions.put(Descendant.NAME, new LuceneDescendant()); + + functions.put(FTSTerm.NAME, new LuceneFTSTerm()); + functions.put(FTSPhrase.NAME, new LuceneFTSPhrase()); + functions.put(FTSProximity.NAME, new LuceneFTSProximity()); + functions.put(FTSRange.NAME, new LuceneFTSRange()); + functions.put(FTSPrefixTerm.NAME, new LuceneFTSPrefixTerm()); + functions.put(FTSWildTerm.NAME, new LuceneFTSWildTerm()); + functions.put(FTSFuzzyTerm.NAME, new LuceneFTSFuzzyTerm()); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#createColumn(org.alfresco.repo.search.impl.querymodel.Function, + * java.util.List, java.lang.String) + */ + public Column createColumn(Function function, Map functionArguments, String alias) + { + return new LuceneColumn(function, functionArguments, alias); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#createConjunction(java.util.List) + */ + public Constraint createConjunction(List constraints) + { + return new LuceneConjunction(constraints); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#createDisjunction(java.util.List) + */ + public Constraint createDisjunction(List constraints) + { + return new LuceneDisjunction(constraints); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#createFunctionalConstraint(org.alfresco.repo.search.impl.querymodel.Function, + * java.util.List) + */ + public Constraint createFunctionalConstraint(Function function, Map functionArguments) + { + return new LuceneFunctionalConstraint(function, functionArguments); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#createJoin(org.alfresco.repo.search.impl.querymodel.Source, + * org.alfresco.repo.search.impl.querymodel.Source, org.alfresco.repo.search.impl.querymodel.JoinType, + * org.alfresco.repo.search.impl.querymodel.Constraint) + */ + public Join createJoin(Source left, Source right, JoinType joinType, Constraint joinCondition) + { + return new LuceneJoin(left, right, joinType, joinCondition); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#createLiteralArgument(java.lang.String, + * org.alfresco.service.namespace.QName, java.io.Serializable) + */ + public LiteralArgument createLiteralArgument(String name, QName type, Serializable value) + { + return new LuceneLiteralArgument(name, type, value); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#createOrdering(org.alfresco.repo.search.impl.querymodel.DynamicArgument, + * org.alfresco.repo.search.impl.querymodel.Order) + */ + public Ordering createOrdering(Column column, Order order) + { + return new LuceneOrdering(column, order); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#createParameterArgument(java.lang.String, + * java.lang.String) + */ + public ParameterArgument createParameterArgument(String name, String parameterName) + { + return new LuceneParameterArgument(name, parameterName); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#createPropertyArgument(java.lang.String, + * org.alfresco.service.namespace.QName) + */ + public PropertyArgument createPropertyArgument(String name, boolean queryable, boolean orderable, String selector, String propertyName) + { + return new LucenePropertyArgument(name, queryable, orderable, selector, propertyName); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#createQuery(java.util.List, + * org.alfresco.repo.search.impl.querymodel.Source, org.alfresco.repo.search.impl.querymodel.Constraint, + * java.util.List) + */ + public Query createQuery(List columns, Source source, Constraint constraint, List orderings) + { + return new LuceneQuery(columns, source, constraint, orderings); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#createSelector(org.alfresco.service.namespace.QName, + * java.lang.String) + */ + public Selector createSelector(QName classQName, String alias) + { + return new LuceneSelector(classQName, alias); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#getFunction(java.lang.String) + */ + public Function getFunction(String functionName) + { + Function function = functions.get(functionName); + if (function != null) + { + return function; + } + else + { + // scan + for (String key : functions.keySet()) + { + if (key.equalsIgnoreCase(functionName)) + { + return functions.get(key); + } + } + return null; + } + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#createSelectorArgument(java.lang.String, + * java.lang.String) + */ + public SelectorArgument createSelectorArgument(String name, String selectorAlias) + { + return new LuceneSelectorArgument(name, selectorAlias); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#createListArgument(java.lang.String, + * java.util.ArrayList) + */ + public ListArgument createListArgument(String name, ArrayList arguments) + { + return new LuceneListArgument(name, arguments); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.QueryModelFactory#createFunctionArgument(java.lang.String, + * org.alfresco.repo.search.impl.querymodel.Function, java.util.List) + */ + public FunctionArgument createFunctionArgument(String name, Function function, Map functionArguments) + { + return new LuceneFunctionArgument(name, function, functionArguments); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneSelector.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneSelector.java new file mode 100644 index 0000000000..e526781897 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneSelector.java @@ -0,0 +1,75 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.JoinType; +import org.alfresco.repo.search.impl.querymodel.impl.BaseSelector; +import org.alfresco.service.namespace.QName; + +/** + * @author andyh + * + */ +public class LuceneSelector extends BaseSelector implements LuceneQueryBuilderComponent +{ + + /** + * @param type QName + * @param alias String + */ + public LuceneSelector(QName type, String alias) + { + super(type, alias); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, org.apache.lucene.search.BooleanQuery) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + switch(getJoinType()) + { + case INNER: + case NONE: + return lqpa.getFieldQuery("CLASS", getType().toString()); + case LEFT: + return lqpa.getMatchAllNodesQuery(); + case RIGHT: + default: + throw new IllegalArgumentException(); + } + + } + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneSelectorArgument.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneSelectorArgument.java new file mode 100644 index 0000000000..6a30bce61b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneSelectorArgument.java @@ -0,0 +1,47 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene; + +import org.alfresco.repo.search.impl.querymodel.impl.BaseSelectorArgument; + +/** + * @author andyh + * + */ +public class LuceneSelectorArgument extends BaseSelectorArgument +{ + + /** + * @param name String + * @param selector String + */ + public LuceneSelectorArgument(String name, String selector) + { + super(name, selector); + // TODO Auto-generated constructor stub + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneChild.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneChild.java new file mode 100644 index 0000000000..52c8b70f3f --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneChild.java @@ -0,0 +1,114 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.ArrayList; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.adaptor.lucene.QueryConstants; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Child; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; + +/** + * @author andyh + * + */ +public class LuceneChild extends Child implements LuceneQueryBuilderComponent +{ + + /** + * + */ + public LuceneChild() + { + super(); + } + + private StoreRef getStore(LuceneQueryBuilderContext luceneContext) + { + ArrayList stores = luceneContext.getLuceneQueryParserAdaptor().getSearchParameters().getStores(); + if(stores.size() < 1) + { + // default + return StoreRef.STORE_REF_WORKSPACE_SPACESSTORE; + } + return stores.get(0); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + Argument argument = functionArgs.get(ARG_PARENT); + String id = (String) argument.getValue(functionContext); + argument = functionArgs.get(ARG_SELECTOR); + if(argument != null) + { + String selector = (String) argument.getValue(functionContext); + if(!selectors.contains(selector)) + { + throw new QueryModelException("Unkown selector "+selector); + } + } + else + { + if(selectors.size() > 1) + { + throw new QueryModelException("Selector must be specified for child constraint (IN_FOLDER) and join"); + } + } + + NodeRef nodeRef; + if(NodeRef.isNodeRef(id)) + { + nodeRef= new NodeRef(id); + } + else + { + // assume id is the node uuid e.g. for OpenCMIS + StoreRef storeRef = getStore(luceneContext); + nodeRef = new NodeRef(storeRef, id); + } + + Q query = lqpa.getFieldQuery(QueryConstants.FIELD_PARENT, nodeRef.toString()); + return query; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneDescendant.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneDescendant.java new file mode 100644 index 0000000000..48ad0577a6 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneDescendant.java @@ -0,0 +1,134 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.ArrayList; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.adaptor.lucene.QueryConstants; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Descendant; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.cmr.repository.StoreRef; + +/** + * @author andyh + * + */ +public class LuceneDescendant extends Descendant implements LuceneQueryBuilderComponent +{ + + /** + * + */ + public LuceneDescendant() + { + super(); + } + + private StoreRef getStore(LuceneQueryBuilderContext luceneContext) + { + ArrayList stores = luceneContext.getLuceneQueryParserAdaptor().getSearchParameters().getStores(); + if(stores.size() < 1) + { + // default + return StoreRef.STORE_REF_WORKSPACE_SPACESSTORE; + } + return stores.get(0); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + Argument argument = functionArgs.get(ARG_ANCESTOR); + String id = (String) argument.getValue(functionContext); + argument = functionArgs.get(ARG_SELECTOR); + if(argument != null) + { + String selector = (String) argument.getValue(functionContext); + if(!selectors.contains(selector)) + { + throw new QueryModelException("Unkown selector "+selector); + } + } + else + { + if(selectors.size() > 1) + { + throw new QueryModelException("Selector must be specified for child constraint (IN_TREE) and join"); + } + } + + NodeRef nodeRef; + if(NodeRef.isNodeRef(id)) + { + nodeRef = new NodeRef(id); + } + else + { + // assume id is the node uuid e.g. for OpenCMIS + StoreRef storeRef = getStore(luceneContext); + nodeRef = new NodeRef(storeRef, id); + } + + // Lucene world + if(functionContext.getNodeService() != null) + { + if(!functionContext.getNodeService().exists(nodeRef)) + { + throw new QueryModelException("Object does not exist: "+id); + } + Path path = functionContext.getNodeService().getPath(nodeRef); + StringBuilder builder = new StringBuilder(path.toPrefixString(luceneContext.getNamespacePrefixResolver())); + builder.append("//*"); + Q query = lqpa.getFieldQuery(QueryConstants.FIELD_PATH, builder.toString()); + return query; + } + // SOLR + else + { + Q query = lqpa.getFieldQuery(QueryConstants.FIELD_ANCESTOR, nodeRef.toString()); + return query; + } + + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneEquals.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneEquals.java new file mode 100644 index 0000000000..b623b89a1e --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneEquals.java @@ -0,0 +1,77 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Equals; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * @author andyh + * + */ +public class LuceneEquals extends Equals implements LuceneQueryBuilderComponent +{ + /** + * + */ + public LuceneEquals() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + setPropertyAndStaticArguments(functionArgs); + + Q query = functionContext.buildLuceneEquality(lqpa, getPropertyName(), getStaticArgument().getValue(functionContext), PredicateMode.ANY, functionContext.getLuceneFunction(getFunctionArgument())); + + if(query == null) + { + throw new QueryModelException("No query time mapping for property "+getPropertyArgument().getPropertyName()+", it should not be allowed in predicates"); + } + + return query; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneExists.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneExists.java new file mode 100644 index 0000000000..744aced99c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneExists.java @@ -0,0 +1,72 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Exists; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; + +/** + * @author andyh + */ +public class LuceneExists extends Exists implements LuceneQueryBuilderComponent +{ + + /** + * + */ + public LuceneExists() + { + super(); + } + + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + PropertyArgument propertyArgument = (PropertyArgument) functionArgs.get(ARG_PROPERTY); + Argument inverseArgument = functionArgs.get(ARG_NOT); + Boolean not = DefaultTypeConverter.INSTANCE.convert(Boolean.class, inverseArgument.getValue(functionContext)); + + Q query = functionContext.buildLuceneExists(lqpa, propertyArgument.getPropertyName(), not); + + if (query == null) + { + throw new QueryModelException("No query time mapping for property " + propertyArgument.getPropertyName() + ", it should not be allowed in predicates"); + } + + return query; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSFuzzyTerm.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSFuzzyTerm.java new file mode 100644 index 0000000000..a98ea4c7da --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSFuzzyTerm.java @@ -0,0 +1,87 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSFuzzyTerm; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * Fuzzy matching + * @author andyh + * + */ +public class LuceneFTSFuzzyTerm extends FTSFuzzyTerm implements LuceneQueryBuilderComponent +{ + + /** + * + */ + public LuceneFTSFuzzyTerm() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + Argument argument = functionArgs.get(ARG_TERM); + String term = (String) argument.getValue(functionContext); + argument = functionArgs.get(ARG_MIN_SIMILARITY); + Float minSimilarity = (Float) argument.getValue(functionContext); + + PropertyArgument propArg = (PropertyArgument) functionArgs.get(ARG_PROPERTY); + Q query; + if (propArg != null) + { + String prop = propArg.getPropertyName(); + query = lqpa.getFuzzyQuery(functionContext.getLuceneFieldName(prop), term, minSimilarity); + } + else + { + query = lqpa.getFuzzyQuery(lqpa.getField(), term, minSimilarity); + + } + return query; + } + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSPhrase.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSPhrase.java new file mode 100644 index 0000000000..c296b6ceb5 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSPhrase.java @@ -0,0 +1,92 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.AnalysisMode; +import org.alfresco.repo.search.adaptor.lucene.LuceneFunction; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSPhrase; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * @author andyh + * + */ +public class LuceneFTSPhrase extends FTSPhrase implements LuceneQueryBuilderComponent +{ + /** + * + */ + public LuceneFTSPhrase() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + Argument argument = functionArgs.get(ARG_PHRASE); + String term = (String) argument.getValue(functionContext); + + Integer slop = Integer.valueOf(lqpa.getPhraseSlop()); + argument = functionArgs.get(ARG_SLOP); + if(argument != null) + { + slop = (Integer) argument.getValue(functionContext); + } + + argument = functionArgs.get(ARG_TOKENISATION_MODE); + AnalysisMode mode = (AnalysisMode) argument.getValue(functionContext); + + PropertyArgument propArg = (PropertyArgument) functionArgs.get(ARG_PROPERTY); + Q query; + if (propArg != null) + { + String prop = propArg.getPropertyName(); + query = lqpa.getFieldQuery(functionContext.getLuceneFieldName(prop), term, mode, slop, LuceneFunction.FIELD); + } + else + { + query = lqpa.getFieldQuery(lqpa.getField(), term, mode, slop, LuceneFunction.FIELD); + } + return query; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSPrefixTerm.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSPrefixTerm.java new file mode 100644 index 0000000000..d0ce618ecf --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSPrefixTerm.java @@ -0,0 +1,89 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.AnalysisMode; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSPrefixTerm; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * Perfix term + * @author andyh + * + */ +public class LuceneFTSPrefixTerm extends FTSPrefixTerm implements LuceneQueryBuilderComponent +{ + /** + * + */ + public LuceneFTSPrefixTerm() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + Argument argument = functionArgs.get(ARG_TERM); + String term = (String) argument.getValue(functionContext); + // strip trailing wildcard * + term = term.substring(0, term.length()-1); + + argument = functionArgs.get(ARG_TOKENISATION_MODE); + AnalysisMode mode = (AnalysisMode) argument.getValue(functionContext); + + PropertyArgument propArg = (PropertyArgument) functionArgs.get(ARG_PROPERTY); + Q query; + if (propArg != null) + { + String prop = propArg.getPropertyName(); + query = lqpa.getPrefixQuery(functionContext.getLuceneFieldName(prop), term, mode); + } + else + { + query = lqpa.getPrefixQuery(lqpa.getField(), term, mode); + + } + return query; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSProximity.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSProximity.java new file mode 100644 index 0000000000..7d1c45461c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSProximity.java @@ -0,0 +1,101 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSProximity; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * Proximity + * @author andyh + * + */ +public class LuceneFTSProximity extends FTSProximity implements LuceneQueryBuilderComponent +{ + + /** + * + */ + public LuceneFTSProximity() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + Argument argument = functionArgs.get(ARG_FIRST); + String first = (String) argument.getValue(functionContext); + argument = functionArgs.get(ARG_LAST); + String last = (String) argument.getValue(functionContext); + + int slop = 100; + argument = functionArgs.get(ARG_SLOP); + if(argument != null) + { + String val = (String) argument.getValue(functionContext); + try + { + slop = Integer.parseInt(val); + } + catch(NumberFormatException nfe) + { + // ignore rubbish + } + } + + + PropertyArgument propArg = (PropertyArgument) functionArgs.get(ARG_PROPERTY); + Q query; + if (propArg != null) + { + String prop = propArg.getPropertyName(); + query = lqpa.getSpanQuery(functionContext.getLuceneFieldName(prop), first, last, slop, true); + } + else + { + query = lqpa.getSpanQuery(lqpa.getField(), first, last, slop, true); + + } + return query; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSRange.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSRange.java new file mode 100644 index 0000000000..5979d52cd9 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSRange.java @@ -0,0 +1,89 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.AnalysisMode; +import org.alfresco.repo.search.adaptor.lucene.LuceneFunction; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSRange; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * Range + * @author andyh + * + */ +public class LuceneFTSRange extends FTSRange implements LuceneQueryBuilderComponent +{ + /** + * + */ + public LuceneFTSRange() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + Argument argument = functionArgs.get(ARG_FROM_INC); + Boolean fromInc = (Boolean) argument.getValue(functionContext); + argument = functionArgs.get(ARG_FROM); + String from = (String) argument.getValue(functionContext); + argument = functionArgs.get(ARG_TO); + String to = (String) argument.getValue(functionContext); + argument = functionArgs.get(ARG_TO_INC); + Boolean toInc = (Boolean) argument.getValue(functionContext); + + PropertyArgument propArg = (PropertyArgument) functionArgs.get(ARG_PROPERTY); + Q query; + if (propArg != null) + { + String prop = propArg.getPropertyName(); + query = lqpa.getRangeQuery(functionContext.getLuceneFieldName(prop), from, to, fromInc, toInc, AnalysisMode.DEFAULT, LuceneFunction.FIELD); + } + else + { + query = lqpa.getRangeQuery(lqpa.getField(), from, to, fromInc, toInc, AnalysisMode.DEFAULT, LuceneFunction.FIELD); + } + return query; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSTerm.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSTerm.java new file mode 100644 index 0000000000..740539049a --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSTerm.java @@ -0,0 +1,85 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.AnalysisMode; +import org.alfresco.repo.search.adaptor.lucene.LuceneFunction; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSTerm; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * @author andyh + */ +public class LuceneFTSTerm extends FTSTerm implements LuceneQueryBuilderComponent +{ + /** + * + */ + public LuceneFTSTerm() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + Argument argument = functionArgs.get(ARG_TERM); + String term = (String) argument.getValue(functionContext); + argument = functionArgs.get(ARG_TOKENISATION_MODE); + AnalysisMode mode = (AnalysisMode) argument.getValue(functionContext); + + PropertyArgument propArg = (PropertyArgument) functionArgs.get(ARG_PROPERTY); + Q query; + if (propArg != null) + { + String prop = propArg.getPropertyName(); + query = lqpa.getFieldQuery(functionContext.getLuceneFieldName(prop), term, mode, LuceneFunction.FIELD); + } + else + { + query = lqpa.getFieldQuery(lqpa.getField(), term, mode, LuceneFunction.FIELD); + + } + return query; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSWildTerm.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSWildTerm.java new file mode 100644 index 0000000000..5c886112c7 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSWildTerm.java @@ -0,0 +1,89 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.AnalysisMode; +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSWildTerm; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * Wild Card + * @author andyh + * + */ +public class LuceneFTSWildTerm extends FTSWildTerm implements LuceneQueryBuilderComponent +{ + + /** + * + */ + public LuceneFTSWildTerm() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + Argument argument = functionArgs.get(ARG_TERM); + String term = (String) argument.getValue(functionContext); + + argument = functionArgs.get(ARG_TOKENISATION_MODE); + AnalysisMode mode = (AnalysisMode) argument.getValue(functionContext); + + PropertyArgument propArg = (PropertyArgument) functionArgs.get(ARG_PROPERTY); + Q query; + if (propArg != null) + { + String prop = propArg.getPropertyName(); + query = lqpa.getWildcardQuery(functionContext.getLuceneFieldName(prop), term, mode); + } + else + { + query = lqpa.getWildcardQuery(lqpa.getField(), term, mode); + + } + return query; + } + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneGreaterThan.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneGreaterThan.java new file mode 100644 index 0000000000..508184f4e5 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneGreaterThan.java @@ -0,0 +1,77 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.GreaterThan; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * @author andyh + */ +public class LuceneGreaterThan extends GreaterThan implements LuceneQueryBuilderComponent +{ + + /** + * + */ + public LuceneGreaterThan() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + setPropertyAndStaticArguments(functionArgs); + + Q query = functionContext.buildLuceneGreaterThan(lqpa, getPropertyName(), getStaticArgument().getValue(functionContext), PredicateMode.ANY, functionContext.getLuceneFunction(getFunctionArgument())); + + if(query == null) + { + throw new QueryModelException("No query time mapping for property "+getPropertyArgument().getPropertyName()+", it should not be allowed in predicates"); + } + + return query; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneGreaterThanOrEquals.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneGreaterThanOrEquals.java new file mode 100644 index 0000000000..4b7f7df0ca --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneGreaterThanOrEquals.java @@ -0,0 +1,79 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.GreaterThanOrEquals; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * @author andyh + * + */ +public class LuceneGreaterThanOrEquals extends GreaterThanOrEquals implements LuceneQueryBuilderComponent +{ + + /** + * + */ + public LuceneGreaterThanOrEquals() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + setPropertyAndStaticArguments(functionArgs); + + Q query = functionContext.buildLuceneGreaterThanOrEquals(lqpa, getPropertyName(), getStaticArgument().getValue(functionContext), PredicateMode.ANY, functionContext.getLuceneFunction(getFunctionArgument())); + + if(query == null) + { + throw new QueryModelException("No query time mapping for property "+getPropertyArgument().getPropertyName()+", it should not be allowed in predicates"); + } + + return query; + } + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneIn.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneIn.java new file mode 100644 index 0000000000..4986b40dd0 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneIn.java @@ -0,0 +1,90 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.ListArgument; +import org.alfresco.repo.search.impl.querymodel.LiteralArgument; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.In; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; + +/** + * @author andyh + */ +public class LuceneIn extends In implements LuceneQueryBuilderComponent +{ + /** + * + */ + public LuceneIn() + { + super(); + } + + /* + * (non-Javadoc) + * @see + * org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene + * .search.BooleanQuery, org.apache.lucene.search.BooleanQuery, + * org.alfresco.service.cmr.dictionary.DictionaryService, java.lang.String) + */ + @SuppressWarnings("unchecked") + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + PropertyArgument propertyArgument = (PropertyArgument) functionArgs.get(ARG_PROPERTY); + Argument inverseArgument = functionArgs.get(ARG_NOT); + Boolean not = DefaultTypeConverter.INSTANCE.convert(Boolean.class, inverseArgument.getValue(functionContext)); + LiteralArgument modeArgument = (LiteralArgument) functionArgs.get(ARG_MODE); + String modeString = DefaultTypeConverter.INSTANCE.convert(String.class, modeArgument.getValue(functionContext)); + PredicateMode mode = PredicateMode.valueOf(modeString); + + ListArgument listArgument = (ListArgument) functionArgs.get(ARG_LIST); + Collection collection = (Collection) listArgument.getValue(functionContext); + + Q query = functionContext.buildLuceneIn(lqpa, propertyArgument.getPropertyName(), collection, not, mode); + + if (query == null) + { + throw new QueryModelException("No query time mapping for property " + propertyArgument.getPropertyName() + ", it should not be allowed in predicates"); + } + + return query; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLessThan.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLessThan.java new file mode 100644 index 0000000000..307f7799df --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLessThan.java @@ -0,0 +1,79 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.LessThan; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * @author andyh + * + */ +public class LuceneLessThan extends LessThan implements LuceneQueryBuilderComponent +{ + + /** + * + */ + public LuceneLessThan() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + setPropertyAndStaticArguments(functionArgs); + + Q query = functionContext.buildLuceneLessThan(lqpa, getPropertyName(), getStaticArgument().getValue(functionContext), PredicateMode.ANY, functionContext.getLuceneFunction(getFunctionArgument())); + + if(query == null) + { + throw new QueryModelException("No query time mapping for property "+getPropertyArgument().getPropertyName()+", it is not allowed in predicates"); + } + + return query; + } + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLessThanOrEquals.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLessThanOrEquals.java new file mode 100644 index 0000000000..b8161dd238 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLessThanOrEquals.java @@ -0,0 +1,79 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.LessThanOrEquals; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * @author andyh + * + */ +public class LuceneLessThanOrEquals extends LessThanOrEquals implements LuceneQueryBuilderComponent +{ + + /** + * + */ + public LuceneLessThanOrEquals() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + + setPropertyAndStaticArguments(functionArgs); + + Q query = functionContext.buildLuceneLessThanOrEquals(lqpa, getPropertyName(), getStaticArgument().getValue(functionContext), PredicateMode.ANY, functionContext.getLuceneFunction(getFunctionArgument())); + if(query == null) + { + throw new QueryModelException("No query time mapping for property "+getPropertyArgument().getPropertyName()+", it should not be allowed in predicates"); + } + + return query; + } + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLike.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLike.java new file mode 100644 index 0000000000..aa0dac3e8f --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLike.java @@ -0,0 +1,85 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.io.Serializable; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Like; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; + +/** + * @author andyh + * + */ +public class LuceneLike extends Like implements LuceneQueryBuilderComponent +{ + + /** + * + */ + public LuceneLike() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + PropertyArgument propertyArgument = (PropertyArgument) functionArgs.get(ARG_PROPERTY); + Argument inverseArgument = functionArgs.get(ARG_NOT); + Boolean not = DefaultTypeConverter.INSTANCE.convert(Boolean.class, inverseArgument.getValue(functionContext)); + Argument expressionArgument = functionArgs.get(ARG_EXP); + Serializable expression = expressionArgument.getValue(functionContext); + + Q query = functionContext.buildLuceneLike(lqpa, propertyArgument.getPropertyName(), expression, not); + + if (query == null) + { + throw new QueryModelException("No query time mapping for property " + propertyArgument.getPropertyName() + ", it should not be allowed in predicates"); + } + + return query; + } + + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLower.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLower.java new file mode 100644 index 0000000000..11a4c86d53 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneLower.java @@ -0,0 +1,63 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Lower; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * @author andyh + */ +public class LuceneLower extends Lower implements LuceneQueryBuilderComponent +{ + + /** + * + */ + public LuceneLower() + { + super(); + } + + /* + * (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(java.util.Set, + * java.util.Map, org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext, + * org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + throw new QueryModelException("Unsupported function in query " + getName()); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneNotEquals.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneNotEquals.java new file mode 100644 index 0000000000..29bdd63c04 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneNotEquals.java @@ -0,0 +1,78 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.adaptor.lucene.LuceneQueryParserAdaptor; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PredicateMode; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.NotEquals; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * @author andyh + */ +public class LuceneNotEquals extends NotEquals implements LuceneQueryBuilderComponent +{ + + /** + * + */ + public LuceneNotEquals() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + LuceneQueryParserAdaptor lqpa = luceneContext.getLuceneQueryParserAdaptor(); + setPropertyAndStaticArguments(functionArgs); + + Q query = functionContext.buildLuceneInequality(lqpa, getPropertyName(), getStaticArgument().getValue(functionContext), PredicateMode.ANY, functionContext + .getLuceneFunction(getFunctionArgument())); + + if (query == null) + { + throw new QueryModelException("No query time mapping for property " + getPropertyArgument().getPropertyName() + ", it should not be allowed in predicates"); + } + + return query; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LucenePropertyAccessor.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LucenePropertyAccessor.java new file mode 100644 index 0000000000..922b880138 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LucenePropertyAccessor.java @@ -0,0 +1,59 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.PropertyAccessor; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * @author andyh + */ +public class LucenePropertyAccessor extends PropertyAccessor implements LuceneQueryBuilderComponent +{ + /** + * + */ + public LucenePropertyAccessor() + { + super(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(java.util.Set, java.util.Map, org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext, org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + throw new QueryModelException("Unsupported function in query "+getName()); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneScore.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneScore.java new file mode 100644 index 0000000000..8407d39021 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneScore.java @@ -0,0 +1,61 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Score; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * @author andyh + * + */ +public class LuceneScore extends Score implements LuceneQueryBuilderComponent +{ + + /** + * + */ + public LuceneScore() + { + super(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(java.util.Set, java.util.Map, org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext, org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + throw new QueryModelException("Unsupported function in query "+getName()); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneUpper.java b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneUpper.java new file mode 100644 index 0000000000..330ccd78a3 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneUpper.java @@ -0,0 +1,60 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.QueryModelException; +import org.alfresco.repo.search.impl.querymodel.impl.functions.Upper; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; + +/** + * @author andyh + * + */ +public class LuceneUpper extends Upper implements LuceneQueryBuilderComponent +{ + /** + * + */ + public LuceneUpper() + { + super(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(java.util.Set, java.util.Map, org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext, org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext) + */ + public Q addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws E + { + throw new QueryModelException("Unsupported function in query "+getName()); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/security/authentication/AlfrescoSecureContext.java b/data-model/src/main/java/org/alfresco/repo/security/authentication/AlfrescoSecureContext.java new file mode 100644 index 0000000000..fa326aedfd --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/security/authentication/AlfrescoSecureContext.java @@ -0,0 +1,79 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.security.authentication; + +import net.sf.acegisecurity.Authentication; +import net.sf.acegisecurity.context.security.SecureContext; + +/** + * Extensions for the Alfresco security context. + * + * This is based on the Linux model and supports real, effective and stored authorities + * + * The real authority is used for auditing and reporting who the user is etc. + * The effective authority is used for permission checks. + * + * RunAs support leaves the real authority and changes only the effective authority + * That means "special" code can run code as system but still be audited as Joe + * + * In the future scrips etc can support a setUId flag and run as the owner of the script. + * If the script chooses to do this .... + * A method invocation could do the same (after entry security checks) + * + * TODO: extent runAs to take a nodeRef context - it can then set the stored atc and set this as effective if required. + * + * @author andyh + * + */ +public interface AlfrescoSecureContext extends SecureContext +{ + /** + * Get the effective authentication - used for permission checks + * @return Authentication + */ + public Authentication getEffectiveAuthentication(); + + /** + * Get the real authenticaiton - used for auditing and everything else + * @return Authentication + */ + public Authentication getRealAuthentication(); + + /** + * Set the effective authentication held by the context + * + * @param effictiveAuthentication Authentication + */ + public void setEffectiveAuthentication(Authentication effictiveAuthentication); + + /** + * Set the real authentication held by the context + * + * @param realAuthentication Authentication + */ + public void setRealAuthentication(Authentication realAuthentication); + +} diff --git a/data-model/src/main/java/org/alfresco/repo/security/authentication/AlfrescoSecureContextImpl.java b/data-model/src/main/java/org/alfresco/repo/security/authentication/AlfrescoSecureContextImpl.java new file mode 100644 index 0000000000..17d7f277dd --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/security/authentication/AlfrescoSecureContextImpl.java @@ -0,0 +1,169 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.security.authentication; + +import net.sf.acegisecurity.Authentication; +import net.sf.acegisecurity.context.ContextInvalidException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Hold an Alfresco extended security context + * + * @author andyh + * + */ +public class AlfrescoSecureContextImpl implements AlfrescoSecureContext +{ + Log logger = LogFactory.getLog(getClass()); + + private static final long serialVersionUID = -8893133731693272549L; + + private Authentication realAuthentication; + + private Authentication effectiveAuthentication; + + /** + * ACEGI + */ + public Authentication getAuthentication() + { + return getEffectiveAuthentication(); + } + + /** + * ACEGI + */ + public void setAuthentication(Authentication newAuthentication) + { + setEffectiveAuthentication(newAuthentication); + } + + /** + * ACEGI + */ + public void validate() throws ContextInvalidException + { + if (effectiveAuthentication == null) + { + throw new ContextInvalidException("Effective authentication not set"); + } + } + + public Authentication getEffectiveAuthentication() + { + return effectiveAuthentication; + } + + public Authentication getRealAuthentication() + { + return realAuthentication; + } + + public void setEffectiveAuthentication(Authentication effictiveAuthentication) + { + if (logger.isTraceEnabled()) + { + logger.trace("Setting effective authentication to: " + AuthenticationUtil.getMaskedUsername(effictiveAuthentication)); + } + this.effectiveAuthentication = effictiveAuthentication; + } + + public void setRealAuthentication(Authentication realAuthentication) + { + if (logger.isTraceEnabled()) + { + logger.trace("Setting real authentication to: " + AuthenticationUtil.getMaskedUsername(realAuthentication)); + } + this.realAuthentication = realAuthentication; + } + + @Override + public int hashCode() + { + final int PRIME = 31; + int result = 1; + result = PRIME * result + ((effectiveAuthentication == null) ? 0 : effectiveAuthentication.hashCode()); + result = PRIME * result + ((realAuthentication == null) ? 0 : realAuthentication.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final AlfrescoSecureContextImpl other = (AlfrescoSecureContextImpl) obj; + if (effectiveAuthentication == null) + { + if (other.effectiveAuthentication != null) + return false; + } + else if (!effectiveAuthentication.equals(other.effectiveAuthentication)) + return false; + if (realAuthentication == null) + { + if (other.realAuthentication != null) + return false; + } + else if (!realAuthentication.equals(other.realAuthentication)) + return false; + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + + if (realAuthentication == null) + { + builder.append("Real authentication = null"); + } + else + { + builder.append("Real authentication = " + AuthenticationUtil.getMaskedUsername(realAuthentication)); + } + builder.append(", "); + + if (effectiveAuthentication == null) + { + builder.append("Effective authentication = null"); + } + else + { + builder.append("Effective authentication = " +AuthenticationUtil.getMaskedUsername(effectiveAuthentication)); + } + builder.append(", "); + + return builder.toString(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/security/authentication/AuthenticationDiagnostic.java b/data-model/src/main/java/org/alfresco/repo/security/authentication/AuthenticationDiagnostic.java new file mode 100644 index 0000000000..fc1baacd70 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/security/authentication/AuthenticationDiagnostic.java @@ -0,0 +1,160 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.security.authentication; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * Diagnostic information for a failed authentication. + * + * Contains a list of steps which have failed or succeeded. + * The key and arguments can be used to form human readable messages from a message bundle. + */ +public class AuthenticationDiagnostic implements Serializable +{ + /** + * + */ + private static final long serialVersionUID = -936231318594794088L; + + // Level 0 - validation + public static final String STEP_KEY_VALIDATION_AUTHENTICATOR_NOT_FOUND="authentication.ldap.validation.authenticator.notfound"; + + public static final String STEP_KEY_VALIDATION_AUTHENTICATOR_NOT_ACTIVE="authentication.ldap.validation.authenticator.notactive"; + + // Level 0 - validation + public static final String STEP_KEY_VALIDATION="authentication.step.ldap.validation"; + + // Level 1 - connecting to authentication provider + public static final String STEP_KEY_LDAP_CONNECTING="authentication.step.ldap.connecting"; + public static final String STEP_KEY_LDAP_CONNECTED="authentication.step.ldap.connected"; + + // Level 2 - using the authentication provider + public static final String STEP_KEY_LDAP_AUTHENTICATION="authentication.step.ldap.authentication"; + + public static final String STEP_KEY_LDAP_LOOKUP_USER="authentication.step.ldap.lookup"; + public static final String STEP_KEY_LDAP_LOOKEDUP_USER="authentication.step.ldap.lookedup"; + + public static final String STEP_KEY_LDAP_FORMAT_USER="authentication.step.ldap.format.user"; + + // Level 2 - using the authentication provider + public static final String STEP_KEY_LDAP_SEARCH="authentication.ldap.search"; + + + private Liststeps = new ArrayList(10); + + public void addStep(AuthenticationStep step) + { + steps.add(step); + } + + /** + * + * @param key String + * @param success boolean + */ + public void addStep(String key, boolean success) + { + AuthenticationStepImpl step = new AuthenticationStepImpl(key); + step.success = success; + + addStep(step); + } + + /** + * + * @param key String + * @param success boolean + * @param args Object[] + */ + public void addStep(String key, boolean success, Object[] args) + { + AuthenticationStepImpl step = new AuthenticationStepImpl(key); + step.success = success; + step.args = args; + + addStep(step); + } + + public List getSteps() + { + return steps; + } +} + + + +class AuthenticationStepImpl implements AuthenticationStep, Serializable +{ + private static final long serialVersionUID = -445668784415288394L; + String key; + boolean success = false; + Object[] args; + + public AuthenticationStepImpl(String key) + { + this.key = key; + } + + @Override + public String getKey() + { + return key; + } + + @Override + public boolean isSuccess() + { + return success; + } + + @Override + public Object[] getArgs() + { + return args; + } + + public String toString() + { + return "Authentication Step Impl key:" + key + ", is success:" + success; + } + + @Override + public String getMessage() + { + String message = I18NUtil.getMessage(getKey(), getArgs()); + + if(message == null) + { + return key; + } + return message; + } +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/repo/security/authentication/AuthenticationException.java b/data-model/src/main/java/org/alfresco/repo/security/authentication/AuthenticationException.java new file mode 100644 index 0000000000..107692619d --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/security/authentication/AuthenticationException.java @@ -0,0 +1,124 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.security.authentication; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.error.AlfrescoRuntimeException; + +/** + * Alfresco Authentication Exception and wrapper + * + * @author andyh + * + */ +@AlfrescoPublicApi +public class AuthenticationException extends AlfrescoRuntimeException +{ + /** + * + */ + private static final long serialVersionUID = 3546647620128092466L; + + // Diagnostic information to assist with problem determination + AuthenticationDiagnostic diagnostic; + + public AuthenticationException(String msg) + { + super(msg); + } + + public AuthenticationException(String msg, Object[]args) + { + super(msg, args); + } + + public AuthenticationException(String msg, Throwable cause) + { + super(msg, cause); + } + + public AuthenticationException(String msg, Object[] args, Throwable cause) + { + super(msg, cause); + } + + /** + * Authentication Exception + * @param msg human readable message + * @param diagnostic diagnostic information about how the authentication succeeded/failed + */ + public AuthenticationException(String msg, AuthenticationDiagnostic diagnostic) + { + super(msg); + this.diagnostic = diagnostic; + } + + /** + * Authentication Exception + * @param msg human readable message + * @param diagnostic diagnostic information about how the authentication succeeded/failed + */ + public AuthenticationException(String msg, Object[] args, AuthenticationDiagnostic diagnostic) + { + super(msg, args); + this.diagnostic = diagnostic; + } + + /** + * Authentication Exception + * @param msg key for human readable message + * @param diagnostic diagnostic information about how the authentication succeeded/failed + * @param cause stack trace of the exception + */ + public AuthenticationException(String msg, AuthenticationDiagnostic diagnostic, Throwable cause) + { + super(msg, cause); + this.diagnostic = diagnostic; + } + + /** + * Authentication Exception + * @param msg key for human readable message + * @param diagnostic diagnostic information about how the authentication succeeded/failed + * @param args arguments for human readable message + * @param cause stack trace of the exception + */ + public AuthenticationException(String msg, AuthenticationDiagnostic diagnostic, Object[] args, Throwable cause) + { + super(msg, args, cause); + this.diagnostic = diagnostic; + } + + /** + * Get the authentication diagnostic + * @return the authentication diagnostic + */ + public AuthenticationDiagnostic getDiagnostic() + { + return diagnostic; + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/security/authentication/AuthenticationStep.java b/data-model/src/main/java/org/alfresco/repo/security/authentication/AuthenticationStep.java new file mode 100644 index 0000000000..2152f982e3 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/security/authentication/AuthenticationStep.java @@ -0,0 +1,53 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.security.authentication; + +public interface AuthenticationStep +{ + /** + *Get the key for this step + * @return the key + */ + public String getKey(); + + /** + * is success + * @return true success + */ + public boolean isSuccess(); + + /** + * Get the arguments for this step + * @return the arguments + */ + public Object[] getArgs(); + + /** + * get a localised human readable message for this key/arguments + * @return the message for this step + */ + public String getMessage(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java b/data-model/src/main/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java new file mode 100644 index 0000000000..93972805b9 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/security/authentication/AuthenticationUtil.java @@ -0,0 +1,779 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.security.authentication; + +import java.util.Stack; + +import net.sf.acegisecurity.Authentication; +import net.sf.acegisecurity.GrantedAuthority; +import net.sf.acegisecurity.GrantedAuthorityImpl; +import net.sf.acegisecurity.UserDetails; +import net.sf.acegisecurity.context.Context; +import net.sf.acegisecurity.context.ContextHolder; +import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; +import net.sf.acegisecurity.providers.dao.User; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.tenant.TenantContextHolder; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.util.EqualsHelper; +import org.alfresco.util.Pair; +import org.alfresco.util.log.NDC; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.InitializingBean; + +/** + * Utility helper methods to change the authenticated context for threads. + */ +@AlfrescoPublicApi +public class AuthenticationUtil implements InitializingBean +{ + static Log logger = LogFactory.getLog(AuthenticationUtil.class); + @AlfrescoPublicApi + public interface RunAsWork + { + /** + * Method containing the work to be done in the user transaction. + * + * @return Return the result of the operation + */ + Result doWork() throws Exception; + } + + private static boolean initialized = false; + + public static final String SYSTEM_USER_NAME = "System"; + private static String defaultAdminUserName = PermissionService.ADMINISTRATOR_AUTHORITY; + private static String defaultGuestUserName = PermissionService.GUEST_AUTHORITY; + private static boolean mtEnabled = false; + + /* (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception + { + // at this point default admin and guest names have been assigned + initialized = true; + } + + public void setDefaultAdminUserName(String defaultAdminUserName) + { + AuthenticationUtil.defaultAdminUserName = defaultAdminUserName; + } + + public void setDefaultGuestUserName(String defaultGuestUserName) + { + AuthenticationUtil.defaultGuestUserName = defaultGuestUserName; + } + + public static void setMtEnabled(boolean mtEnabled) + { + if (logger.isDebugEnabled()) + { + logger.debug("MT is enabled: " + mtEnabled); + } + AuthenticationUtil.mtEnabled = mtEnabled; + } + + public static boolean isMtEnabled() + { + return AuthenticationUtil.mtEnabled; + } + + public static String maskUsername(String userName) + { + if (userName != null) + { + try + { + if (userName.length() >= 2) + { + return userName.substring(0, 2) + new String(new char[(userName.length() - 2)]).replace("\0", "*"); + } + } + catch (Exception e) + { + if (logger.isDebugEnabled()) + { + logger.debug("Failed to mask the username because: " + e.getMessage(), e); + } + } + return userName; + } + return null; + } + + public static String getMaskedUsername(Authentication authentication) + { + String extractedUsername = null; + if (authentication != null && authentication.getPrincipal() != null) + { + extractedUsername = getUserName(authentication); + } + return maskUsername(extractedUsername); + } + + public AuthenticationUtil() + { + super(); + } + + /** + * Utility method to create an authentication token + */ + private static UsernamePasswordAuthenticationToken getAuthenticationToken(String userName, UserDetails providedDetails) + { + UserDetails ud = null; + if (userName.equals(SYSTEM_USER_NAME)) + { + GrantedAuthority[] gas = new GrantedAuthority[1]; + gas[0] = new GrantedAuthorityImpl("ROLE_SYSTEM"); + ud = new User(SYSTEM_USER_NAME, "", true, true, true, true, gas); + } + else if (userName.equalsIgnoreCase(getGuestUserName())) + { + GrantedAuthority[] gas = new GrantedAuthority[0]; + ud = new User(getGuestUserName().toLowerCase(), "", true, true, true, true, gas); + } + else + { + if (providedDetails.getUsername().equals(userName)) + { + ud = providedDetails; + } + else + { + throw new AuthenticationException("Provided user details do not match the user name"); + } + } + + UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(ud, "", ud.getAuthorities()); + auth.setDetails(ud); + auth.setAuthenticated(true); + return auth; + } + + /** + * Default implementation that makes an ACEGI object on the fly + */ + private static UserDetails getDefaultUserDetails(String userName) + { + GrantedAuthority[] gas = new GrantedAuthority[1]; + gas[0] = new GrantedAuthorityImpl("ROLE_AUTHENTICATED"); + UserDetails ud = new User(userName, "", true, true, true, true, gas); + return ud; + } + + /** + * Extract the username from the authentication. + */ + private static String getUserName(Authentication authentication) + { + if (authentication.getPrincipal() instanceof UserDetails) + { + return ((UserDetails) authentication.getPrincipal()).getUsername(); + } + else + { + return authentication.getPrincipal().toString(); + } + } + + /** + * Authenticate as the Admin user. The Admin user will be authenticated and all operations + * with be run in the context of this Admin user. + * + * @return the authentication token + */ + public static Authentication setAdminUserAsFullyAuthenticatedUser() + { + return setFullyAuthenticatedUser(getAdminUserName()); + } + + /** + * Authenticate as the given user. The user will be authenticated and all operations + * with be run in the context of this user. + * + * @param userName the user name + * @return the authentication token + */ + public static Authentication setFullyAuthenticatedUser(String userName) + { + return setFullyAuthenticatedUser(userName, getDefaultUserDetails(userName)); + } + + private static Authentication setFullyAuthenticatedUser(String userNameIn, UserDetails providedDetails) throws AuthenticationException + { + if (userNameIn == null) + { + throw new AuthenticationException("Null user name"); + } + + try + { + Pair userTenant = AuthenticationUtil.getUserTenant(userNameIn); + final String userName = userTenant.getFirst(); + final String tenantDomain = userTenant.getSecond(); + + UsernamePasswordAuthenticationToken auth = getAuthenticationToken(userName, providedDetails); + Authentication authentication = setFullAuthentication(auth); + + TenantContextHolder.setTenantDomain(tenantDomain); + + return authentication; + } + catch (net.sf.acegisecurity.AuthenticationException ae) + { + throw new AuthenticationException(ae.getMessage(), ae); + } + } + + /** + * Re-authenticate using a previously-created authentication. + */ + public static Authentication setFullAuthentication(Authentication authentication) + { + if (authentication == null) + { + clearCurrentSecurityContext(); + return null; + } + else + { + if (logger.isTraceEnabled()) + { + logger.trace("Setting fully authenticated principal: " + getMaskedUsername(authentication)); + } + Context context = ContextHolder.getContext(); + AlfrescoSecureContext sc = null; + if ((context == null) || !(context instanceof AlfrescoSecureContext)) + { + sc = new AlfrescoSecureContextImpl(); + ContextHolder.setContext(sc); + if (logger.isTraceEnabled()) + { + logger.trace("Setting new secure context: " + sc + " on thread: " + Thread.currentThread().getName()); + } + } + else + { + sc = (AlfrescoSecureContext) context; + } + authentication.setAuthenticated(true); + // Sets real and effective + sc.setRealAuthentication(authentication); + sc.setEffectiveAuthentication(authentication); + return authentication; + } + } + + /** + * WARN: Advanced usage only.
+ * Set the system user as the currently running user for authentication purposes. + * + * @return Authentication + * + * @see #setRunAsUser(String) + */ + public static Authentication setRunAsUserSystem() + { + return setRunAsUser(SYSTEM_USER_NAME); + } + + /** + * WARN: Advanced usage only.
+ * Switch to the given user for all authenticated operations. The original, authenticated user + * can still be found using {@link #getFullyAuthenticatedUser()}. + * + * @param userName the user to run as + * @return the new authentication + */ + public static Authentication setRunAsUser(String userName) + { + return setRunAsUser(userName, getDefaultUserDetails(userName)); + } + + /*package*/ static Authentication setRunAsUser(String userName, UserDetails providedDetails) throws AuthenticationException + { + if (userName == null) + { + throw new AuthenticationException("Null user name"); + } + + try + { + UsernamePasswordAuthenticationToken auth = getAuthenticationToken(userName, providedDetails); + return setRunAsAuthentication(auth); + } + catch (net.sf.acegisecurity.AuthenticationException ae) + { + throw new AuthenticationException(ae.getMessage(), ae); + } + } + + /*package*/ static Authentication setRunAsAuthentication(Authentication authentication) + { + if (authentication == null) + { + clearCurrentSecurityContext(); + return null; + } + else + { + if (logger.isTraceEnabled()) + { + logger.trace("Setting RunAs principal: " + getMaskedUsername(authentication)); + } + Context context = ContextHolder.getContext(); + AlfrescoSecureContext sc = null; + if ((context == null) || !(context instanceof AlfrescoSecureContext)) + { + sc = new AlfrescoSecureContextImpl(); + ContextHolder.setContext(sc); + if (logger.isTraceEnabled()) + { + logger.trace("Setting new secure context: " + sc + " on thread: " + Thread.currentThread().getName()); + } + } + else + { + sc = (AlfrescoSecureContext) context; + } + authentication.setAuthenticated(true); + if (sc.getRealAuthentication() == null) + { + if (logger.isTraceEnabled()) + { + logger.trace("There is no fully authenticated principal. Setting fully authenticated principal: " + getMaskedUsername(authentication)); + } + sc.setRealAuthentication(authentication); + } + sc.setEffectiveAuthentication(authentication); + return authentication; + } + } + + /** + * Get the current authentication for application of permissions. This includes + * the any overlay details set by {@link #setRunAsUser(String)}. + * + * @return Authentication Returns the running authentication + * @throws AuthenticationException + */ + public static Authentication getRunAsAuthentication() throws AuthenticationException + { + Context context = ContextHolder.getContext(); + if ((context == null) || !(context instanceof AlfrescoSecureContext)) + { + return null; + } + return ((AlfrescoSecureContext) context).getEffectiveAuthentication(); + } + + /** + * WARN: Advanced usage only.
+ * Get the authentication for that was set by an real authentication. + * + * @return Authentication Returns the real authentication + * @throws AuthenticationException + */ + public static Authentication getFullAuthentication() throws AuthenticationException + { + Context context = ContextHolder.getContext(); + if ((context == null) || !(context instanceof AlfrescoSecureContext)) + { + return null; + } + return ((AlfrescoSecureContext) context).getRealAuthentication(); + } + + /** + * Get the user that is currently in effect for purposes of authentication. This includes + * any overlays introduced by {@link #setRunAsUser(String) runAs}. + * + * @return Returns the name of the user + * @throws AuthenticationException + */ + public static String getRunAsUser() throws AuthenticationException + { + Context context = ContextHolder.getContext(); + if ((context == null) || !(context instanceof AlfrescoSecureContext)) + { + return null; + } + AlfrescoSecureContext ctx = (AlfrescoSecureContext) context; + if (ctx.getEffectiveAuthentication() == null) + { + return null; + } + return getUserName(ctx.getEffectiveAuthentication()); + } + + public static boolean isRunAsUserTheSystemUser() + { + String runAsUser = getRunAsUser(); + if ((runAsUser != null) && isMtEnabled()) + { + // get base username + int idx = runAsUser.indexOf(TenantService.SEPARATOR); + if (idx != -1) + { + runAsUser = runAsUser.substring(0, idx); + } + } + return EqualsHelper.nullSafeEquals(runAsUser, AuthenticationUtil.SYSTEM_USER_NAME); + } + + /** + * Get the fully authenticated user. + * It returns the name of the user that last authenticated and excludes any overlay authentication set + * by {@link #runAs(org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork, String) runAs}. + * + * @return Returns the name of the authenticated user + * @throws AuthenticationException + */ + public static String getFullyAuthenticatedUser() throws AuthenticationException + { + Context context = ContextHolder.getContext(); + if ((context == null) || !(context instanceof AlfrescoSecureContext)) + { + return null; + } + AlfrescoSecureContext ctx = (AlfrescoSecureContext) context; + if (ctx.getRealAuthentication() == null) + { + return null; + } + return getUserName(ctx.getRealAuthentication()); + } + + /** + * Get the name of the system user + * + * @return system user name + */ + public static String getSystemUserName() + { + return SYSTEM_USER_NAME; + } + + /** + * Get the name of the default admin user (the admin user created during bootstrap) + * + * @return admin user name + */ + public static String getAdminUserName() + { + if (!initialized) + { + throw new IllegalStateException("AuthenticationUtil not yet initialised; default admin username not available"); + } + + if (isMtEnabled()) + { + String runAsUser = AuthenticationUtil.getRunAsUser(); + if (runAsUser != null) + { + String tenantDomain = AuthenticationUtil.getUserTenant(runAsUser).getSecond(); + + if (! TenantService.DEFAULT_DOMAIN.equals(tenantDomain)) + { + return defaultAdminUserName + TenantService.SEPARATOR + tenantDomain; + } + } + } + + return defaultAdminUserName; + } + + /* + * Get the name of admin role + */ + public static String getAdminRoleName() + { + return PermissionService.ADMINISTRATOR_AUTHORITY; + } + + /** + * Get the name of the Guest User + */ + public static String getGuestUserName() + { + if (!initialized) + { + throw new IllegalStateException("AuthenticationUtil not yet initialised; default guest username not available"); + } + return defaultGuestUserName; + } + + /** + * Get the name of the guest role + */ + public static String getGuestRoleName() + { + return PermissionService.GUEST_AUTHORITY; + } + + /** + * Remove the current security information + */ + public static void clearCurrentSecurityContext() + { + if (logger.isTraceEnabled()) + { + logger.trace("Removing the current security information for thread: " + Thread.currentThread().getName()); + } + ContextHolder.setContext(null); + InMemoryTicketComponentImpl.clearCurrentSecurityContext(); + + NDC.remove(); + + TenantContextHolder.clearTenantDomain(); + } + + /** + * Execute a unit of work as a given user. The thread's authenticated user will be returned to its normal state + * after the call. + * + * @param runAsWork + * the unit of work to do + * @param uid + * the user ID + * @return Returns the work's return value + */ + public static R runAs(RunAsWork runAsWork, String uid) + { + Authentication originalFullAuthentication = AuthenticationUtil.getFullAuthentication(); + Authentication originalRunAsAuthentication = AuthenticationUtil.getRunAsAuthentication(); + + final R result; + try + { + if (originalFullAuthentication == null) + { + AuthenticationUtil.setFullyAuthenticatedUser(uid); + } + else + { + // TODO remove - this should be obsolete now we're using TenantContextHolder + /* + if ((originalRunAsAuthentication != null) && (isMtEnabled())) + { + String originalRunAsUserName = getUserName(originalRunAsAuthentication); + int idx = originalRunAsUserName.indexOf(TenantService.SEPARATOR); + if ((idx != -1) && (idx < (originalRunAsUserName.length() - 1))) + { + if (uid.equals(AuthenticationUtil.getSystemUserName())) + { + uid = uid + TenantService.SEPARATOR + originalRunAsUserName.substring(idx + 1); + } + } + } + */ + AuthenticationUtil.setRunAsUser(uid); + } + logNDC(uid); + result = runAsWork.doWork(); + return result; + } + catch (Throwable exception) + { + // Re-throw the exception + if (exception instanceof RuntimeException) + { + throw (RuntimeException) exception; + } + else + { + throw new RuntimeException("Error during run as.", exception); + } + } + finally + { + if (originalFullAuthentication == null) + { + AuthenticationUtil.clearCurrentSecurityContext(); + logNDC(null); + } + else + { + AuthenticationUtil.setFullAuthentication(originalFullAuthentication); + AuthenticationUtil.setRunAsAuthentication(originalRunAsAuthentication); + + logNDC(getUserName(originalFullAuthentication)); + } + } + } + + public static R runAsSystem(RunAsWork runAsWork) + { + return runAs(runAsWork, getSystemUserName()); + } + + static class ThreadLocalStack extends ThreadLocal> + { + /* (non-Javadoc) + * @see java.lang.ThreadLocal#initialValue() + */ + @Override + protected Stack initialValue() + { + return new Stack(); + } + } + + private static ThreadLocal> threadLocalFullAuthenticationStack = new ThreadLocalStack(); + private static ThreadLocal> threadLocalRunAsAuthenticationStack = new ThreadLocalStack(); + + private static ThreadLocal> threadLocalTenantDomainStack = new ThreadLocal>() + { + @Override + protected Stack initialValue() + { + return new Stack(); + } + }; + + /** + * Push the current authentication context onto a threadlocal stack. + */ + public static void pushAuthentication() + { + Authentication originalFullAuthentication = AuthenticationUtil.getFullAuthentication(); + Authentication originalRunAsAuthentication = AuthenticationUtil.getRunAsAuthentication(); + threadLocalFullAuthenticationStack.get().push(originalFullAuthentication); + threadLocalRunAsAuthenticationStack.get().push(originalRunAsAuthentication); + + threadLocalTenantDomainStack.get().push(TenantContextHolder.getTenantDomain()); + if (logger.isTraceEnabled()) + { + logger.trace("Pushed authentication in thread: " + Thread.currentThread().getName()); + } + } + + /** + * Pop the authentication context from a threadlocal stack. + */ + public static void popAuthentication() + { + Authentication originalFullAuthentication = threadLocalFullAuthenticationStack.get().pop(); + Authentication originalRunAsAuthentication = threadLocalRunAsAuthenticationStack.get().pop(); + + if (originalFullAuthentication == null) + { + AuthenticationUtil.clearCurrentSecurityContext(); + } + else + { + AuthenticationUtil.setFullAuthentication(originalFullAuthentication); + AuthenticationUtil.setRunAsAuthentication(originalRunAsAuthentication); + } + + String originalTenantDomain = threadLocalTenantDomainStack.get().pop(); + TenantContextHolder.setTenantDomain(originalTenantDomain); + if (logger.isTraceEnabled()) + { + logger.trace("Popped authentication in thread: " + Thread.currentThread().getName()); + } + } + + /** + * Logs the current authenticated users + */ + public static void logAuthenticatedUsers() + { + if (logger.isDebugEnabled()) + { + logger.debug( + "Authentication: \n" + + " Fully authenticated: " + maskUsername(getFullyAuthenticatedUser()) + "\n" + + " Run as: " + maskUsername(getRunAsUser())); + } + } + + public static void logNDC(String userNameIn) + { + NDC.remove(); + + if (userNameIn != null) + { + if (isMtEnabled()) + { + Pair userTenant = AuthenticationUtil.getUserTenant(userNameIn); + final String userName = userTenant.getFirst(); + final String tenantDomain = userTenant.getSecond(); + if (! TenantService.DEFAULT_DOMAIN.equals(tenantDomain)) + { + NDC.push("Tenant:" +tenantDomain + " User:" + maskUsername(userName)); + } + else + { + NDC.push("User:" + maskUsername(userName)); + } + } + else + { + NDC.push("User:" + maskUsername(userNameIn)); + } + } + } + + // + // Return username and current tenant domain. If current tenant domain is not set then + // get implied tenant domain. For example: bob@acme.com => bob@acme.com, acme.com + // + public static Pair getUserTenant(String userName) + { + String tenantDomain = TenantContextHolder.getTenantDomain(); + if (tenantDomain == null) + { + tenantDomain = TenantService.DEFAULT_DOMAIN; + + if ((userName != null) && isMtEnabled()) + { + // MT implied domain from username (for backwards compatibility) + int idx = userName.indexOf(TenantService.SEPARATOR); + if ((idx > 0) && (idx < (userName.length()-1))) + { + tenantDomain = userName.substring(idx+1); + if (tenantDomain.indexOf(TenantService.SEPARATOR) > 0) + { + throw new AlfrescoRuntimeException("Unexpected tenant: "+tenantDomain+" (contains @)"); + } + + if (logger.isDebugEnabled()) + { + logger.debug("Tenant domain implied: userName=" + maskUsername(userName) + ", tenantDomain=" + tenantDomain); + } + } + } + } + return new Pair(userName, tenantDomain); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/security/authentication/InMemoryTicketComponentImpl.java b/data-model/src/main/java/org/alfresco/repo/security/authentication/InMemoryTicketComponentImpl.java new file mode 100644 index 0000000000..132ced6f69 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/security/authentication/InMemoryTicketComponentImpl.java @@ -0,0 +1,711 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.security.authentication; + +import java.io.Serializable; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; +import java.util.zip.CRC32; + +import org.alfresco.repo.cache.SimpleCache; +import org.alfresco.service.cmr.repository.datatype.Duration; +import org.alfresco.util.GUID; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.safehaus.uuid.UUIDGenerator; +import org.alfresco.util.ParameterCheck; + +/** + * Store tickets in memory. They can be distributed in a cluster via the cache + * + * @author andyh + */ +public class InMemoryTicketComponentImpl implements TicketComponent +{ + /** + * Ticket prefix + */ + public static final String GRANTED_AUTHORITY_TICKET_PREFIX = "TICKET_"; + + private static Log logger = LogFactory.getLog(InMemoryTicketComponentImpl.class); + + private static ThreadLocal currentTicket = new ThreadLocal(); + private boolean ticketsExpire; + private Duration validDuration; + private boolean oneOff; + private String guid; + private SimpleCache ticketsCache; // Can't use Ticket as it's private + private ExpiryMode expiryMode = ExpiryMode.AFTER_INACTIVITY; + private boolean useSingleTicketPerUser = true; + + /** + * IOC constructor + */ + public InMemoryTicketComponentImpl() + { + super(); + guid = GUID.generate(); + } + + /** + * Set the ticket cache to support clustering + */ + public void setTicketsCache(SimpleCache ticketsCache) + { + this.ticketsCache = ticketsCache; + } + + /** + * @param useSingleTicketPerUser the useSingleTicketPerUser to set + */ + public void setUseSingleTicketPerUser(boolean useSingleTicketPerUser) + { + this.useSingleTicketPerUser = useSingleTicketPerUser; + } + + /** + * @return the useSingleTicketPerUser + */ + public boolean getUseSingleTicketPerUser() + { + return useSingleTicketPerUser; + } + + /** + * Are tickets single use + */ + @Deprecated + public void setOneOff(boolean oneOff) + { + this.oneOff = oneOff; + if (this.oneOff) + { + logger.warn("The 'oneOff' feature has been deprecated and will be removed in a future version. " + + "This feature may not work as intended even in the current version"); + } + } + + /** + * Do tickets expire + */ + public void setTicketsExpire(boolean ticketsExpire) + { + this.ticketsExpire = ticketsExpire; + } + + /** + * How should tickets expire. + */ + public void setExpiryMode(String expiryMode) + { + this.expiryMode = ExpiryMode.valueOf(expiryMode); + } + + /** + * How long are tickets valid (XML duration as a string) + */ + public void setValidDuration(String validDuration) + { + this.validDuration = new Duration(validDuration); + } + + /** + * All put operations into ticketsCache should go through this method, + * so we can debug/trace ticket problems easier from the logs + */ + private void putTicketIntoTicketsCache(Ticket ticket) + { + if (logger.isTraceEnabled()) + { + logger.trace("Putting into ticketsCache " + ticketsCache.toString() + " ticket: " + ticket); + } + ticketsCache.put(ticket.getTicketId(), ticket); + } + + /** + * All remove operations from ticketsCache should go through this method, + * so we can debug/trace ticket problems easier from the logs + */ + private void removeTicketFromTicketsCache(String ticketId) + { + if (logger.isTraceEnabled()) + { + logger.trace("Removing ticket from ticketsCache: " + ticketId); + } + ticketsCache.remove(ticketId); + } + + @Override + public String getNewTicket(String userName) throws AuthenticationException + { + Ticket ticket = null; + if(useSingleTicketPerUser) + { + ticket = findNonExpiredUserTicket(userName); + } + + if(ticket == null) + { + Date expiryDate = null; + if (ticketsExpire) + { + expiryDate = Duration.add(new Date(), validDuration); + } + ticket = new Ticket(ticketsExpire ? expiryMode : ExpiryMode.DO_NOT_EXPIRE, expiryDate, userName, validDuration); + putTicketIntoTicketsCache(ticket); + } + + String ticketString = GRANTED_AUTHORITY_TICKET_PREFIX + ticket.getTicketId(); + currentTicket.set(ticketString); + if (logger.isTraceEnabled()) + { + logger.trace("Setting the current ticket for this thread: " + Thread.currentThread().getName() + " to: " + ticketString); + } + return ticketString; + } + + private Ticket findNonExpiredUserTicket(String userName) + { + for (String key : ticketsCache.getKeys()) + { + Ticket ticket = ticketsCache.get(key); + if (ticket != null) + { + if(ticket.getUserName().equals(userName)) + { + Ticket newTicket = ticket.getNewEntry(); + if(newTicket != null) + { + if (newTicket != ticket) + { + putTicketIntoTicketsCache(newTicket); + } + return newTicket; + } + } + } + } + return null; + } + + @Override + public String validateTicket(String ticketString) throws AuthenticationException + { + if (logger.isTraceEnabled()) + { + logger.trace("Validating ticket: " + ticketString); + } + String ticketKey = getTicketKey(ticketString); + Ticket ticket = ticketsCache.get(ticketKey); + if (ticket == null) + { + final String msg = "Missing ticket for " + ticketString; + if (logger.isDebugEnabled()) + { + logger.debug(msg); + } + throw new AuthenticationException(msg); + } + Ticket newTicket = ticket.getNewEntry(); + if (newTicket == null) + { + final String msg = "Ticket expired for " + ticketString; + if (logger.isDebugEnabled()) + { + logger.debug(msg); + } + throw new TicketExpiredException(msg); + } + if (oneOff) + { + //this feature is deprecated + removeTicketFromTicketsCache(ticketKey); + } + else if (newTicket != ticket) + { + putTicketIntoTicketsCache(newTicket); + } + currentTicket.set(ticketString); + if (logger.isTraceEnabled()) + { + logger.trace("Setting the current ticket for this thread: " + Thread.currentThread().getName() + " to: " + ticketString); + } + return newTicket.getUserName(); + } + + /** + * Helper method to find a ticket + * + * @param ticketString String + * @return - the ticket + */ + private Ticket getTicketByTicketString(String ticketString) + { + Ticket ticket = ticketsCache.get(getTicketKey(ticketString)); + return ticket; + } + + /** + * Helper method to extract the ticket id from the ticket string + * + * @param ticketString String + * @return - the ticket key + */ + private String getTicketKey(String ticketString) + { + if (ticketString == null) + { + return null; + } + else if (ticketString.length() < GRANTED_AUTHORITY_TICKET_PREFIX.length()) + { + throw new AuthenticationException(ticketString + " is an invalid ticket format"); + } + + String key = ticketString.substring(GRANTED_AUTHORITY_TICKET_PREFIX.length()); + return key; + } + + @Override + public void invalidateTicketById(String ticketString) + { + String key = ticketString.substring(GRANTED_AUTHORITY_TICKET_PREFIX.length()); + removeTicketFromTicketsCache(key); + } + + @Override + public Set getUsersWithTickets(boolean nonExpiredOnly) + { + Date now = new Date(); + Set users = new HashSet(); + for (String key : ticketsCache.getKeys()) + { + Ticket ticket = ticketsCache.get(key); + if (ticket != null) + { + if ((nonExpiredOnly == false) || !ticket.hasExpired(now)) + { + users.add(ticket.getUserName()); + } + } + } + return users; + } + + @Override + public int countTickets(boolean nonExpiredOnly) + { + Date now = new Date(); + if (nonExpiredOnly) + { + int count = 0; + for (String key : ticketsCache.getKeys()) + { + Ticket ticket = ticketsCache.get(key); + if (ticket != null && !ticket.hasExpired(now)) + { + count++; + } + } + return count; + } + else + { + return ticketsCache.getKeys().size(); + } + } + + @Override + public int invalidateTickets(boolean expiredOnly) + { + if (logger.isTraceEnabled()) + { + logger.trace("Invalidate all tickets, expired only: " + expiredOnly); + } + Date now = new Date(); + int count = 0; + if (!expiredOnly) + { + count = ticketsCache.getKeys().size(); + if (logger.isTraceEnabled()) + { + logger.trace("Clearing all tickets from the ticketsCache, that used to have size: " + count); + } + ticketsCache.clear(); + } + else + { + Set toRemove = new HashSet(); + for (String key : ticketsCache.getKeys()) + { + Ticket ticket = ticketsCache.get(key); + if (ticket == null || ticket.hasExpired(now)) + { + count++; + toRemove.add(key); + } + } + for (String id : toRemove) + { + removeTicketFromTicketsCache(id); + } + } + return count; + } + + @Override + public void invalidateTicketByUser(String userName) + { + Set toRemove = new HashSet(); + + for (String key : ticketsCache.getKeys()) + { + Ticket ticket = ticketsCache.get(key); + // Hack: The getKeys() call might return keys for null marker objects, yielding null values + if (ticket == null) + { + continue; + } + if (ticket.getUserName().equals(userName)) + { + toRemove.add(ticket.getTicketId()); + } + } + + for (String id : toRemove) + { + removeTicketFromTicketsCache(id); + } + } + + @Override + public int hashCode() + { + final int PRIME = 31; + int result = 1; + result = PRIME * result + ((guid == null) ? 0 : guid.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final InMemoryTicketComponentImpl other = (InMemoryTicketComponentImpl) obj; + if (guid == null) + { + if (other.guid != null) + return false; + } + else if (!guid.equals(other.guid)) + return false; + return true; + } + + /** + * Ticket + * + * @author andyh + */ + public static class Ticket implements Serializable + { + private static final long serialVersionUID = -5904510560161261049L; + + private final ExpiryMode expires; + + private final Date expiryDate; + + private final String userName; + + private final String ticketId; + + private final Duration validDuration; + + private final Duration testDuration; + + Ticket(ExpiryMode expires, Date expiryDate, String userName, Duration validDuration) + { + checkValidTicketParameters(expires, expiryDate, userName, validDuration); + this.expires = expires; + this.expiryDate = expiryDate; + this.userName = userName; + this.validDuration = validDuration; + this.testDuration = validDuration.divide(2); + final String guid = UUIDGenerator.getInstance().generateRandomBasedUUID().toString(); + + this.ticketId = computeTicketId(expires, expiryDate, userName, guid); + + if (logger.isTraceEnabled()) + { + logger.trace("Creating new ticket for user: " + AuthenticationUtil.maskUsername(userName) + " with ticketId: " + this.ticketId); + } + } + + private static String computeTicketId(ExpiryMode expires, Date expiryDate, String userName, String guid) + { + String encode = expires.toString() + getExpireDateAsString(expiryDate) + userName + guid; + MessageDigest digester; + String ticketId; + try + { + digester = MessageDigest.getInstance("SHA-1"); + ticketId = new String(Hex.encodeHex(digester.digest(encode.getBytes()))); + } + catch (NoSuchAlgorithmException e) + { + try + { + digester = MessageDigest.getInstance("MD5"); + ticketId = new String(Hex.encodeHex(digester.digest(encode.getBytes()))); + } + catch (NoSuchAlgorithmException e1) + { + CRC32 crc = new CRC32(); + crc.update(encode.getBytes()); + byte[] bytes = new byte[4]; + long value = crc.getValue(); + bytes[0] = (byte) (value & 0xFF); + value >>>= 4; + bytes[1] = (byte) (value & 0xFF); + value >>>= 4; + bytes[2] = (byte) (value & 0xFF); + value >>>= 4; + bytes[3] = (byte) (value & 0xFF); + ticketId = new String(Hex.encodeHex(bytes)); + } + } + return ticketId; + } + + private Ticket(ExpiryMode expires, Date expiryDate, String userName, Duration validDuration, String ticketId) + { + checkValidTicketParameters(expires, expiryDate, userName, validDuration); + ParameterCheck.mandatory("ticketId", ticketId); + + this.expires = expires; + this.expiryDate = expiryDate; + this.userName = userName; + this.validDuration = validDuration; + Duration tenPercent = validDuration.divide(10); + this.testDuration = validDuration.subtract(tenPercent); + this.ticketId = ticketId; + + if (logger.isTraceEnabled()) + { + logger.trace( + "Creating (cloning) new ticket for user: " + AuthenticationUtil.maskUsername(userName) + " with ticketId: " + this.ticketId); + } + } + + private static void checkValidTicketParameters(ExpiryMode expires, Date expiryDate, String userName, Duration validDuration) + { + ParameterCheck.mandatory("expires mode", expires); + ParameterCheck.mandatoryString("userName", userName); + ParameterCheck.mandatory("validDuration", validDuration); + if (!ExpiryMode.DO_NOT_EXPIRE.equals(expires)) + { + ParameterCheck.mandatory("expiryDate", expiryDate); + } + } + + private static String getExpireDateAsString(Date expiryDate) + { + return (expiryDate == null) ? "" : expiryDate.toString(); + } + + boolean hasExpired(Date now) + { + return ((expiryDate != null) && (expiryDate.compareTo(now) < 0)); + } + + Ticket getNewEntry() + { + switch (expires) + { + case AFTER_FIXED_TIME: + if (hasExpired(new Date())) + { + return null; + } + else + { + return this; + } + + case AFTER_INACTIVITY: + Date now = new Date(); + if (hasExpired(now)) + { + return null; + } + else + { + Duration remaining = new Duration(now, expiryDate); + if(remaining.compareTo(testDuration) < 0) + { + if (logger.isTraceEnabled()) + { + logger.trace("AFTER_INACTIVITY case, Creating new ticket based on the current one that expires at: " + expiryDate); + } + return new Ticket(expires, Duration.add(now, validDuration), userName, validDuration, ticketId); + } + else + { + return this; + } + } + + case DO_NOT_EXPIRE: + default: + return this; + } + } + + public boolean equals(Object o) + { + if (o == this) + { + return true; + } + if (!(o instanceof Ticket)) + { + return false; + } + Ticket t = (Ticket) o; + + return this.ticketId.equals(t.ticketId) && this.userName.equals(t.userName) && this.expires.equals(t.expires) && areTheExpiryDatesEqual(t); + } + + private boolean areTheExpiryDatesEqual(Ticket t) + { + if (ExpiryMode.DO_NOT_EXPIRE.equals(this.expires)) + { + // if we have tickets that do not expire, we don't care about their expiration date + // this.expiryDate should be null + return true; + } + + // in this case this.expiryDate should not ever be null; There are checks in the constructors that validate this; + // but just in case, somehow it is null: print a warning, then fail + if (this.expiryDate == null) + { + logger.warn("expiryDate should not be null in this case"); + } + return this.expiryDate.equals(t.expiryDate); + } + + public int hashCode() + { + return ticketId.hashCode(); + } + + protected ExpiryMode getExpires() + { + return expires; + } + + protected Date getExpiryDate() + { + return expiryDate; + } + + protected String getTicketId() + { + return ticketId; + } + + protected String getUserName() + { + return userName; + } + + @Override + public String toString() + { + return "Ticket with ticketId: " + ticketId + " for user: " + AuthenticationUtil.maskUsername(userName) + " ExpiryMode: " + expires + + " expire date: " + expiryDate + " validDuration: " + validDuration; + } + } + + @Override + public String getAuthorityForTicket(String ticketString) + { + Ticket ticket = getTicketByTicketString(ticketString); + if (ticket == null) + { + return null; + } + return ticket.getUserName(); + } + + @Override + public String getCurrentTicket(String userName, boolean autoCreate) + { + String ticket = currentTicket.get(); + if (ticket == null) + { + return autoCreate ? getNewTicket(userName) : null; + } + String ticketUser = getAuthorityForTicket(ticket); + if (userName.equals(ticketUser)) + { + return ticket; + } + else + { + return autoCreate ? getNewTicket(userName) : null; + } + } + + public void clearCurrentTicket() + { + clearCurrentSecurityContext(); + } + + public static void clearCurrentSecurityContext() + { + String prevTicket = currentTicket.get(); + currentTicket.set(null); + if (logger.isTraceEnabled()) + { + logger.trace("Clearing the current ticket for this thread: " + Thread.currentThread().getName() + " . Previous ticket was: " + prevTicket); + } + } + + public enum ExpiryMode + { + AFTER_INACTIVITY, AFTER_FIXED_TIME, DO_NOT_EXPIRE; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/security/authentication/TicketComponent.java b/data-model/src/main/java/org/alfresco/repo/security/authentication/TicketComponent.java new file mode 100644 index 0000000000..29a16c2c80 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/security/authentication/TicketComponent.java @@ -0,0 +1,150 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.security.authentication; + +import java.util.Set; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.Auditable; + + +/** + * Manage authentication tickets + * + * @author andyh + * + */ +@AlfrescoPublicApi +public interface TicketComponent +{ + /** + * Register a new ticket + * + * @param userName String + * @return - the ticket + * @throws AuthenticationException + */ + public String getNewTicket(String userName) throws AuthenticationException; + + /** + * Get the current ticket + * + * @param userName String + * @param autoCreate + * should we create one automatically if there isn't one? + * @return - the ticket + */ + + public String getCurrentTicket(String userName, boolean autoCreate); + + /** + * Check that a certificate is valid and can be used in place of a login. + * + * Tickets may be rejected because: + *

    + *
  1. The certificate does not exists + *
  2. The status of the user has changed + *
      + *
    1. The user is locked + *
    2. The account has expired + *
    3. The credentials have expired + *
    4. The account is disabled + *
    + *
  3. The ticket may have expired + *
      + *
    1. The ticked my be invalid by timed expiry + *
    2. An attemp to reuse a once only ticket + *
    + *
+ * + * @param ticket String + * @return - the user name + * @throws AuthenticationException + */ + @Auditable(parameters = {"ticket"}, recordable = {false}) + public String validateTicket(String ticket) throws AuthenticationException; + + /** + * Invalidate the tickets by id + * @param ticket String + */ + @Auditable(parameters = {"ticket"}, recordable = {false}) + public void invalidateTicketById(String ticket); + + /** + * Invalidate all user tickets + * + * @param userName String + */ + public void invalidateTicketByUser(String userName); + + /** + * Count tickets + * + * This may be higher than the user count, since a user can have more than one ticket/session + * + * @param nonExpiredOnly true for non expired tickets, false for all (including expired) tickets + * @return int number of tickets + */ + public int countTickets(boolean nonExpiredOnly); + + /** + * Get set of users with tickets + * + * This may be lower than the ticket count, since a user can have more than one ticket/session + * + * @param nonExpiredOnly true for non expired tickets, false for all (including expired) tickets + */ + public Set getUsersWithTickets(boolean nonExpiredOnly); + + /** + * Invalidate tickets + * + * @param expiredOnly true for EXPIRED tickets, false for ALL (including non-expired) tickets + * @return int count of invalidated tickets + */ + public int invalidateTickets(boolean expiredOnly); + + /** + * Get the authority for the given ticket + * + * @param ticket String + * @return the authority + */ + public String getAuthorityForTicket(String ticket); + + /** + * Clear the current ticket + * + */ + public void clearCurrentTicket(); + + /** + * Does this ticket component support a single ticket per user or one ticket for each time they login? + * @return boolean + */ + public boolean getUseSingleTicketPerUser(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/security/authentication/TicketExpiredException.java b/data-model/src/main/java/org/alfresco/repo/security/authentication/TicketExpiredException.java new file mode 100644 index 0000000000..8daa738a75 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/security/authentication/TicketExpiredException.java @@ -0,0 +1,49 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.security.authentication; + +import org.alfresco.api.AlfrescoPublicApi; + +@AlfrescoPublicApi +public class TicketExpiredException extends AuthenticationException +{ + + /** + * + */ + private static final long serialVersionUID = 3257572801815590969L; + + public TicketExpiredException(String msg) + { + super(msg); + } + + public TicketExpiredException(String msg, Throwable cause) + { + super(msg, cause); + } + +} diff --git a/data-model/src/main/java/org/alfresco/repo/tenant/SingleTServiceImpl.java b/data-model/src/main/java/org/alfresco/repo/tenant/SingleTServiceImpl.java new file mode 100644 index 0000000000..9d124d7f20 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/tenant/SingleTServiceImpl.java @@ -0,0 +1,212 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.tenant; + +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + +/** + * Empty Tenant Service implementation (for Single-Tenant / Single-Instance) + */ + +public class SingleTServiceImpl implements TenantService +{ + public NodeRef getName(NodeRef nodeRef) + { + return nodeRef; + } + + public NodeRef getName(NodeRef inNodeRef, NodeRef nodeRef) + { + return nodeRef; + } + + public StoreRef getName(StoreRef storeRef) + { + return storeRef; + } + + public ChildAssociationRef getName(ChildAssociationRef childAssocRef) + { + return childAssocRef; + } + + public AssociationRef getName(AssociationRef assocRef) + { + return assocRef; + } + + public StoreRef getName(String username, StoreRef storeRef) + { + return storeRef; + } + + public QName getName(QName name) + { + return name; + } + + public QName getName(NodeRef inNodeRef, QName name) + { + return name; + } + + public String getName(String name) + { + return name; + } + + public QName getBaseName(QName name, boolean forceForNonTenant) + { + return name; + } + + public NodeRef getBaseName(NodeRef nodeRef) + { + return nodeRef; + } + + public NodeRef getBaseName(NodeRef nodeRef, boolean forceForNonTenant) + { + return nodeRef; + } + + public StoreRef getBaseName(StoreRef storeRef) + { + return storeRef; + } + + public ChildAssociationRef getBaseName(ChildAssociationRef childAssocRef) + { + return childAssocRef; + } + + public ChildAssociationRef getBaseName(ChildAssociationRef childAssocRef, boolean forceForNonTenant) + { + return childAssocRef; + } + + public AssociationRef getBaseName(AssociationRef assocRef) + { + return assocRef; + } + + public String getBaseName(String name) + { + return name; + } + + + public String getBaseName(String name, boolean forceForNonTenant) + { + return name; + } + + public String getBaseNameUser(String name) + { + return name; + } + + public void checkDomainUser(String username) + { + // NOOP + } + + public void checkDomain(String name) + { + // NOOP + } + + public NodeRef getRootNode(NodeService nodeService, SearchService searchService, NamespaceService namespaceService, String rootPath, NodeRef rootNodeRef) + { + return rootNodeRef; + } + + public boolean isTenantUser() + { + return false; + } + + public boolean isTenantUser(String username) + { + return false; + } + + public boolean isTenantName(String name) + { + return false; + } + + public String getUserDomain(String username) + { + return DEFAULT_DOMAIN; + } + + public String getCurrentUserDomain() + { + return DEFAULT_DOMAIN; + } + + public String getDomain(String name) + { + return DEFAULT_DOMAIN; + } + + public String getDomain(String name, boolean checkCurrentDomain) + { + return DEFAULT_DOMAIN; + } + + public String getDomainUser(String baseUsername, String tenantDomain) + { + return baseUsername; + } + + public Tenant getTenant(String tenantDomain) + { + return null; + } + + public boolean isEnabled() + { + return false; + } + + /** + * In a single tenant system, always return the DEFAULT_DOMAIN. + * + * @see TenantService + */ + public String getPrimaryDomain(String user) { + return DEFAULT_DOMAIN; + } +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/repo/tenant/Tenant.java b/data-model/src/main/java/org/alfresco/repo/tenant/Tenant.java new file mode 100644 index 0000000000..cfbc89793b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/tenant/Tenant.java @@ -0,0 +1,102 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.tenant; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Tenant + * + */ +@AlfrescoPublicApi +public class Tenant +{ + private String tenantDomain; + + private boolean enabled = false; + + private String rootContentStoreDir = null; // if configured - can be null + + // from Thor - unused + private String dbUrl = null; + + + public Tenant(String tenantDomain, boolean enabled, String rootContentStoreDir, String dbUrl) + { + this.tenantDomain = tenantDomain; + this.enabled = enabled; + this.rootContentStoreDir = rootContentStoreDir; + this.dbUrl = dbUrl; + } + + public String getTenantDomain() + { + return tenantDomain; + } + + public boolean isEnabled() + { + return enabled; + } + + public String getRootContentStoreDir() + { + return rootContentStoreDir; + } + + public String getDbUrl() + { + return dbUrl; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + + ((tenantDomain == null) ? 0 : tenantDomain.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Tenant other = (Tenant) obj; + if (tenantDomain == null) { + if (other.tenantDomain != null) + return false; + } else if (!tenantDomain.equals(other.tenantDomain)) + return false; + return true; + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/tenant/TenantContextHolder.java b/data-model/src/main/java/org/alfresco/repo/tenant/TenantContextHolder.java new file mode 100644 index 0000000000..349ec6af11 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/tenant/TenantContextHolder.java @@ -0,0 +1,89 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.tenant; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Thread local to maintain tenant context for threads. + * + * @author janv + * @since Thor + */ +public class TenantContextHolder +{ + private static Log logger = LogFactory.getLog(TenantContextHolder.class); + + private static final ThreadLocal contextHolder = new ThreadLocal(); + + public static String setTenantDomain(String tenantDomain) + { + String currentTenantDomain = getTenantDomain(); + + if (tenantDomain == null) + { + clearTenantDomain(); + return currentTenantDomain; + } + + // force lower-case + tenantDomain = tenantDomain.toLowerCase(); + + if (tenantDomain.equals(currentTenantDomain)) + { + return currentTenantDomain; + } + + contextHolder.set(tenantDomain); + + if (logger.isTraceEnabled()) + { + logger.trace("Set tenant: "+tenantDomain); + } + + return currentTenantDomain; + } + + public static String getTenantDomain() + { + return (String)contextHolder.get(); + } + + public static void clearTenantDomain() + { + if (logger.isTraceEnabled()) + { + String tenantDomain = getTenantDomain(); + if (! TenantService.DEFAULT_DOMAIN.equals(tenantDomain)) + { + logger.trace("Clear tenant domain (was: "+getTenantDomain()+")"); + } + } + + contextHolder.remove(); + } +} diff --git a/data-model/src/main/java/org/alfresco/repo/tenant/TenantDeployer.java b/data-model/src/main/java/org/alfresco/repo/tenant/TenantDeployer.java new file mode 100644 index 0000000000..fbee505a53 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/tenant/TenantDeployer.java @@ -0,0 +1,49 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.tenant; + + +/** + * Tenant Deployer interface. + *

+ * This interface allows components to be notified of tenant events. + * Components will register with TenantAdminService. + * Also callbacks used during bootstrap (init) and shutdown (destroy) + * + */ + +public interface TenantDeployer +{ + public void onEnableTenant(); + + public void onDisableTenant(); + + // callback for bootstrap (for each tenant) + public void init(); + + // callback for shutdown (for each tenant) + public void destroy(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/tenant/TenantService.java b/data-model/src/main/java/org/alfresco/repo/tenant/TenantService.java new file mode 100644 index 0000000000..d97606d6fa --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/tenant/TenantService.java @@ -0,0 +1,175 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.tenant; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + + +/** + * Tenant Service interface. + *

+ * This interface provides methods to support either ST or MT implementations. + * + */ +@AlfrescoPublicApi +public interface TenantService extends TenantUserService +{ + public static final String SEPARATOR = "@"; + + public static final String DEFAULT_DOMAIN = ""; + + /** + * @return the reference with the tenant-specific ID attached + */ + public NodeRef getName(NodeRef nodeRef); + + /** + * @return the reference with the tenant-specific ID attached + */ + public NodeRef getName(NodeRef inNodeRef, NodeRef nodeRef); + + /** + * @return the reference with the tenant-specific ID attached + */ + public StoreRef getName(StoreRef storeRef); + + /** + * @return the reference with the tenant-specific ID attached + */ + public ChildAssociationRef getName(ChildAssociationRef childAssocRef); + + /** + * @return the reference with the tenant-specific ID attached + */ + public AssociationRef getName(AssociationRef assocRef); + + /** + * @return the reference with the tenant-specific ID attached + */ + public StoreRef getName(String username, StoreRef storeRef); + + /** + * @return the reference with the tenant-specific ID attached + */ + public QName getName(QName name); + + /** + * @return the reference with the tenant-specific ID attached + */ + public QName getName(NodeRef inNodeRef, QName name); + + /** + * @return the reference with the tenant-specific ID attached + */ + public String getName(String name); + + /** + * @return the reference without the tenant-specific ID attached + */ + public QName getBaseName(QName name, boolean forceIfNonTenant); + + /** + * @return the reference without the tenant-specific ID attached + */ + public NodeRef getBaseName(NodeRef nodeRef); + + /** + * @return the reference without the tenant-specific ID attached + */ + public NodeRef getBaseName(NodeRef nodeRef, boolean forceForNonTenant); + + /** + * @return the reference without the tenant-specific ID attached + */ + public StoreRef getBaseName(StoreRef storeRef); + + /** + * @return the reference without the tenant-specific ID attached + */ + public ChildAssociationRef getBaseName(ChildAssociationRef childAssocRef); + + /** + * @return the reference without the tenant-specific ID attached + */ + public ChildAssociationRef getBaseName(ChildAssociationRef childAssocRef, boolean forceIfNonTenant); + + /** + * @return the reference without the tenant-specific ID attached + */ + public AssociationRef getBaseName(AssociationRef assocRef); + + /** + * @return the reference without the tenant-specific ID attached + */ + public String getBaseName(String name); + + /** + * @return the reference without the tenant-specific ID attached + */ + public String getBaseName(String name, boolean forceIfNonTenant); + + public void checkDomainUser(String username); + + public void checkDomain(String name); + + public NodeRef getRootNode(NodeService nodeService, SearchService searchService, NamespaceService namespaceService, String rootPath, NodeRef rootNodeRef); + + public boolean isTenantUser(); + + public boolean isTenantUser(String username); + + public boolean isTenantName(String name); + + public String getUserDomain(String username); + + public Tenant getTenant(String tenantDomain); + + /** + * @return the tenant-specific ID for specified identifier + */ + public String getDomain(String name); + + /** + * @return the tenant-specific ID for specified identifier + */ + public String getDomain(String name, boolean checkCurrentDomain); + + /** + * Get the primary domain for user, if one exists. + * + * @param user The user whose primary domain is to be returned + * @return The primary domain of user, or null if the domain does not exist in the system. + */ + public String getPrimaryDomain(String user); +} diff --git a/data-model/src/main/java/org/alfresco/repo/tenant/TenantUserService.java b/data-model/src/main/java/org/alfresco/repo/tenant/TenantUserService.java new file mode 100644 index 0000000000..5bff9a8ed5 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/tenant/TenantUserService.java @@ -0,0 +1,64 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.tenant; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Interface for Tenant User-Domain functionality. + * + * @author janv + * @author Derek Hulley + * @since 3.0 + */ +@AlfrescoPublicApi +public interface TenantUserService +{ + /** + * @return the username with the tenant-specific ID attached + */ + public String getDomainUser(String baseUsername, String tenantDomain); + + /** + * @return the username without the tenant-specific ID attached + */ + public String getBaseNameUser(String name); + + /** + * @return the tenant-specific ID for current user + */ + public String getCurrentUserDomain(); + + /** + * @return the tenant-specific ID for specified username + */ + public String getUserDomain(String username); + + /** + * @return true if the system is configured to be MT-enabled + */ + public boolean isEnabled(); +} diff --git a/data-model/src/main/java/org/alfresco/repo/tenant/TenantUtil.java b/data-model/src/main/java/org/alfresco/repo/tenant/TenantUtil.java new file mode 100644 index 0000000000..ab68c7d2e7 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/repo/tenant/TenantUtil.java @@ -0,0 +1,175 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.tenant; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.util.ParameterCheck; + +/** + * Utility helper methods to change the tenant context for threads. + * + * @author janv + * @author Nick Smith + * @since 4.2 + */ +public abstract class TenantUtil +{ + public static final String SYSTEM_TENANT = "-system-"; + public static final String DEFAULT_TENANT = "-default-"; + + public interface TenantRunAsWork + { + /** + * Method containing the work to be done + * + * @return Return the result of the operation + */ + Result doWork() throws Exception; + } + + /** + * Execute a unit of work in a given tenant context. The thread's tenant context will be returned to its normal state + * after the call. + * + * @param runAsWork the unit of work to do + * @param uid the user ID + * @param tenantDomain the tenant domain + * @return Returns the work's return value + */ + public static R runAsUserTenant(final TenantRunAsWork runAsWork, final String uid, final String tenantDomain) + { + return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork() + { + public R doWork() + { + return runAsTenant(runAsWork, tenantDomain); + } + }, uid); + } + + /** + * Execute a unit of work in a given tenant context. The thread's tenant context will be returned to its normal state + * after the call. + * + * @param runAsWork the unit of work to do + * @param tenantDomain the tenant domain + * @return Returns the work's return value + */ + public static R runAsTenant(final TenantRunAsWork runAsWork, String tenantDomain) + { + ParameterCheck.mandatory("tenantDomain", tenantDomain); + + if (tenantDomain.indexOf(TenantService.SEPARATOR) > 0) + { + throw new AlfrescoRuntimeException("Unexpected tenant domain: "+tenantDomain+" (should not contain '"+TenantService.SEPARATOR+"')"); + } + + String currentTenantDomain = null; + try + { + currentTenantDomain = TenantContextHolder.setTenantDomain(tenantDomain); + return runAsWork(runAsWork); + } + finally + { + TenantContextHolder.setTenantDomain(currentTenantDomain); + } + } + + public static R runAsDefaultTenant(final TenantRunAsWork runAsWork) + { + // Note: with MT Enterprise, if you're current user is not already part of the default domain then this will switch to System + if (getCurrentDomain().equals(TenantService.DEFAULT_DOMAIN)) + { + return runAsWork(runAsWork); + } + else + { + return runAsSystemTenant(runAsWork, TenantService.DEFAULT_DOMAIN); // force System in default domain + } + } + + // switch tenant and run as System within that tenant + public static R runAsSystemTenant(final TenantRunAsWork runAsWork, final String tenantDomain) + { + return runAsUserTenant(runAsWork, AuthenticationUtil.getSystemUserName(), tenantDomain); + } + + private static R runAsWork(final TenantRunAsWork runAsWork) + { + try + { + return runAsWork.doWork(); + } + catch (Throwable e) + { + // Re-throw the exception + if (e instanceof RuntimeException) + { + throw (RuntimeException) e; + } + throw new RuntimeException("Error encountered while performing TenantUtil.runAsWork: " + e.getMessage(), e); + } + } + + // note: this does not check if tenant is enabled (unlike non-static MultiTServiceImpl.getCurrentUserDomain) + public static String getCurrentDomain() + { + String tenantDomain = TenantContextHolder.getTenantDomain(); + if (tenantDomain == null) + { + tenantDomain = TenantService.DEFAULT_DOMAIN; + } + return tenantDomain; + } + + public static boolean isCurrentDomainDefault() + { + return TenantService.DEFAULT_DOMAIN.equals(getCurrentDomain()); + } + + public static String getTenantDomain(String name) + { + ParameterCheck.mandatory("name", name); + + int idx1 = name.indexOf(TenantService.SEPARATOR); + if (idx1 == 0) + { + int idx2 = name.indexOf(TenantService.SEPARATOR, 1); + if (idx2 != -1) + { + return name.substring(1, idx2); + } + } + return TenantService.DEFAULT_DOMAIN; + } + + public static boolean isDefaultTenantName(String name) + { + return TenantService.DEFAULT_DOMAIN.equals(getTenantDomain(name)); + } +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/service/Auditable.java b/data-model/src/main/java/org/alfresco/service/Auditable.java new file mode 100644 index 0000000000..9fc3bf4c24 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/Auditable.java @@ -0,0 +1,69 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Annotation to defined key and parameter names for the auditing API. + * + * If this annotation is present on a public service interface it will be considered for auditing. If it is not present the method will never be audited. + * + * Note that the service name and method name can be found from the bean definition and the method invocation. + * + * @author Andy Hind + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@AlfrescoPublicApi +public @interface Auditable +{ + /** + * The names of the parameters + * + * @return a String[] of parameter names, the default is an empty array. + */ + String[] parameters() default {}; + + /** + * All method parameters are recorded by default. + * This can be used to stop a parameter being written to the audit log. + */ + boolean[] recordable() default {}; + + /** + * Return object are recorded by default. + * Setting this means they can never be recorded in the audit. + */ + boolean recordReturnedObject() default true; +} diff --git a/data-model/src/main/java/org/alfresco/service/NotAuditable.java b/data-model/src/main/java/org/alfresco/service/NotAuditable.java new file mode 100644 index 0000000000..ce4376e164 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/NotAuditable.java @@ -0,0 +1,49 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Specifically indicate that a method is not to be audited. + * This is a marker annotation. + * + * @author Andy Hind + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@AlfrescoPublicApi +public @interface NotAuditable +{ + +} diff --git a/data-model/src/main/java/org/alfresco/service/PublicService.java b/data-model/src/main/java/org/alfresco/service/PublicService.java new file mode 100644 index 0000000000..e46c2b939c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/PublicService.java @@ -0,0 +1,44 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @deprecated as audit no longer needs to know if a bean is a public service. + */ +@Deprecated +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface PublicService +{ + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/AspectDefinition.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/AspectDefinition.java new file mode 100644 index 0000000000..9d8a0d8618 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/AspectDefinition.java @@ -0,0 +1,39 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Read-only definition of an Aspect. + * + * @author David Caruana + */ +@AlfrescoPublicApi +public interface AspectDefinition extends ClassDefinition +{ + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/AssociationDefinition.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/AssociationDefinition.java new file mode 100644 index 0000000000..d5a232463e --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/AssociationDefinition.java @@ -0,0 +1,144 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.QName; + + +/** + * Read-only definition of an Association. + * + * @author David Caruana + * + */ +@AlfrescoPublicApi +public interface AssociationDefinition extends ClassAttributeDefinition +{ + + /** + * @return defining model + */ + public ModelDefinition getModel(); + + /** + * @return the qualified name + */ + public QName getName(); + + /** + * @deprecated The problem identified in MNT-413 will still exist + * @see org.alfresco.service.cmr.dictionary.AssociationDefinition#getTitle(org.alfresco.service.cmr.i18n.MessageLookup) + */ + public String getTitle(); + + /** + * @deprecated The problem identified in MNT-413 will still exist + * @see org.alfresco.service.cmr.dictionary.AssociationDefinition#getDescription(org.alfresco.service.cmr.i18n.MessageLookup) + */ + public String getDescription(); + + /** + * @return the human-readable title + */ + public String getTitle(MessageLookup messageLookup); + + /** + * @return the human-readable description + */ + public String getDescription(MessageLookup messageLookup); + + /** + * Is this a child association? + * + * @return true => child, false => general relationship + */ + public boolean isChild(); + + /** + * Is this association maintained by the Repository? + * + * @return true => system maintained, false => client may maintain + */ + public boolean isProtected(); + + /** + * @return the source class + */ + public ClassDefinition getSourceClass(); + + /** + * @return the role of the source class in this association? + */ + public QName getSourceRoleName(); + + /** + * Is the source class optional in this association? + * + * @return true => cardinality > 0 + */ + public boolean isSourceMandatory(); + + /** + * Can there be many source class instances in this association? + * + * @return true => cardinality > 1, false => cardinality of 0 or 1 + */ + public boolean isSourceMany(); + + /** + * @return the target class + */ + public ClassDefinition getTargetClass(); + + /** + * @return the role of the target class in this association? + */ + public QName getTargetRoleName(); + + /** + * Is the target class optional in this association? + * + * @return true => cardinality > 0 + */ + public boolean isTargetMandatory(); + + /** + * Is the target class is mandatory, it is enforced? + * + * @return true => enforced + */ + public boolean isTargetMandatoryEnforced(); + + /** + * Can there be many target class instances in this association? + * + * @return true => cardinality > 1, false => cardinality of 0 or 1 + */ + public boolean isTargetMany(); + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ChildAssociationDefinition.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ChildAssociationDefinition.java new file mode 100644 index 0000000000..3d985bf408 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ChildAssociationDefinition.java @@ -0,0 +1,54 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Read-only definition of a Child Association. + * + * @author David Caruana + * + */ +@AlfrescoPublicApi +public interface ChildAssociationDefinition extends AssociationDefinition +{ + + /** + * @return the required name of children (or null if none) + */ + public String getRequiredChildName(); + + /** + * @return whether duplicate child names allowed within this association? + */ + public boolean getDuplicateChildNamesAllowed(); + + /** + * @return whether timestamps should be propagated upwards along primary associations + */ + public boolean getPropagateTimestamps(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ClassAttributeDefinition.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ClassAttributeDefinition.java new file mode 100644 index 0000000000..3c7a959a80 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ClassAttributeDefinition.java @@ -0,0 +1,67 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.service.cmr.dictionary; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.QName; + +/** + * + * @author Nick Smith + */ +@AlfrescoPublicApi +public interface ClassAttributeDefinition +{ + /** + * @return defining model + */ + public ModelDefinition getModel(); + + /** + * @return the qualified name + */ + public QName getName(); + + /** + * @return the human-readable title + */ + public String getTitle(MessageLookup messageLookup); + + /** + * @return the human-readable description + */ + public String getDescription(MessageLookup messageLookup); + + /** + * Is this association or property maintained by the Repository? + * + * @return true => system maintained, false => client may maintain + */ + public boolean isProtected(); + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ClassDefinition.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ClassDefinition.java new file mode 100644 index 0000000000..0534878ad2 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ClassDefinition.java @@ -0,0 +1,165 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.QName; + +/** + * Read-only definition of a Class. + * + * @author David Caruana + */ +@AlfrescoPublicApi +public interface ClassDefinition +{ + /** + * @return defining model + */ + public ModelDefinition getModel(); + + /** + * @return the qualified name of the class + */ + public QName getName(); + + /** + * @deprecated The problem identified in MNT-413 will still exist + */ + public String getTitle(); + + /** + * @deprecated The problem identified in MNT-413 will still exist + */ + public String getDescription(); + + /** + * @return the human-readable class title + */ + public String getTitle(MessageLookup messageLookup); + + /** + * @return the human-readable class description + */ + public String getDescription(MessageLookup messageLookup); + + /** + * @return the super class (or null, if this is the root) + */ + public QName getParentName(); + + /** + * @return true => aspect, false => type + */ + public boolean isAspect(); + + /** + * @return Return true if the type should be archived on delete, false if it should be + * deleted or null if not defined. + */ + public Boolean getArchive(); + + /** + * + * @return Return true if the type should be included in supertypes queries, false if not + * deleted or null if not defined. + */ + public Boolean getIncludedInSuperTypeQuery(); + + /** + * @return the properties of the class, including inherited properties + */ + public Map getProperties(); + + /** + * @return a map containing the default property values, including inherited properties + */ + public Map getDefaultValues(); + + /** + * Fetch all associations for which this is a source type, including child associations. + * + * @return the associations including inherited ones + * @see ChildAssociationDefinition + */ + public Map getAssociations(); + + /** + * @return true => this class supports child associations + */ + public boolean isContainer(); + + /** + * Fetch only child associations for which this is a source type. + * + * @return all child associations applicable to this type, including those + * inherited from super types + */ + public Map getChildAssociations(); + + /** + * Fetch all associations for which this is a target type, including child associations. + * + * @return the associations including inherited ones + */ + // TODO: public Map getTargetAssociations(); + + /** + * @return the default aspects associated with this type + */ + public List getDefaultAspects(); + + /** + * @return the set of default aspects names associated with this type + */ + public Set getDefaultAspectNames(); + + /** + * @param inherited include default aspects inherited from super types + * @return the default aspects + */ + public List getDefaultAspects(boolean inherited); + + /** + * Get the name of the property bundle that defines analyser mappings for this class (keyed by the type of the property) + * @return the resource or null if not set. + */ + public String getAnalyserResourceBundleName(); + + /** + * Get the parent class definition + * + * @return ClassDefinition + */ + public ClassDefinition getParentClassDefinition(); + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/Constraint.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/Constraint.java new file mode 100644 index 0000000000..be58cc7d8b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/Constraint.java @@ -0,0 +1,94 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import java.util.Map; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * The interface for classes that implement constraints on property values. + *

+ * Implementations of the actual constraint code should must not synchronize + * or in any other way block threads. Concurrent access of the evaluation + * method is expected, but will always occur after initialization has completed. + *

+ * Attention to performance is crucial for all implementations as + * instances of this class are heavily used. + *

+ * The constraint implementations can provide standard setter methods that will + * be populated by bean setter injection. Once all the available properties have + * been set, the contraint will be initialized. + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public interface Constraint +{ + /** + * Returns the 'type' of the constraint, this is the identifier given to + * constraint in the configuration. + * + * @return The type + */ + public String getType(); + + /** + * @return the human-readable constraint title (optional) + */ + public String getTitle(); + + /** + * Gets the constraint name. + * + * @return the constraint name. + */ + public String getShortName(); + + /** + * Returns the parameters passed to the instance of the constraint. + * + * @return Map of parameters or an empty Map if none exist + */ + public Map getParameters(); + + /** + * Initializes the constraint with appropriate values, which will depend + * on the implementation itself. This method can be implemented as a + * once-off, i.e. reinitialization does not have to be supported. + */ + public void initialize(); + + /** + * Evaluates a property value according to the implementation and initialization + * parameters provided. + * + * @param value the property value to check + * + * @throws ConstraintException if the value doesn't pass all constraints + */ + public void evaluate(Object value); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ConstraintDefinition.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ConstraintDefinition.java new file mode 100644 index 0000000000..95581ecafd --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ConstraintDefinition.java @@ -0,0 +1,83 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.QName; + +/** + * Property constraint definition + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public interface ConstraintDefinition +{ + /** + * @return defining model + */ + public ModelDefinition getModel(); + + /** + * @return Returns the qualified name of the constraint + */ + public QName getName(); + + /** + * @deprecated The problem identified in MNT-413 will still exist + * @see org.alfresco.service.cmr.dictionary.ConstraintDefinition#getTitle(org.alfresco.service.cmr.i18n.MessageLookup) + */ + public String getTitle(); + + /** + * @deprecated The problem identified in MNT-413 will still exist + * @see org.alfresco.service.cmr.dictionary.ConstraintDefinition#getDescription(org.alfresco.service.cmr.i18n.MessageLookup) + */ + public String getDescription(); + + /** + * @return the human-readable class title + */ + public String getTitle(MessageLookup messageLookup); + + /** + * @return the human-readable class description + */ + public String getDescription(MessageLookup messageLookup); + + /** + * @return Returns the constraint implementation + */ + public Constraint getConstraint(); + + /** + * @return Returns the referenced constraint definition, if any (null for explicit or inline constraint def) + * + * @since 3.2R + */ + public QName getRef(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ConstraintException.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ConstraintException.java new file mode 100644 index 0000000000..1f5d4122fc --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ConstraintException.java @@ -0,0 +1,43 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import org.alfresco.error.AlfrescoRuntimeException; + +/** + * Thrown when property value fails to meet a property constraint. + * + * @author Derek Hulley + */ +public class ConstraintException extends AlfrescoRuntimeException +{ + private static final long serialVersionUID = -3925105163386197586L; + + public ConstraintException(String msgId, Object ... args) + { + super(msgId, args); + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelDefinition.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelDefinition.java new file mode 100644 index 0000000000..9faeb01664 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelDefinition.java @@ -0,0 +1,71 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.service.cmr.dictionary; + +import java.util.Collection; + +/** + * @author Jamal Kaabi-Mofrad + */ +public interface CustomModelDefinition extends ModelDefinition +{ + + /** + * Whether the model is active or not + * + * @return true if the model is active, false otherwise + */ + public boolean isActive(); + + /** + * Returns the model description + * + * @return the model description + */ + public String getDescription(); + + /** + * Returns a {@link Collection} of the model {@link TypeDefinition}s + * + * @return an unmodifiable collection of the model types definitions, or an empty collection + */ + public Collection getTypeDefinitions(); + + /** + * Returns a {@link Collection} of the model {@link AspectDefinition}s + * + * @return an unmodifiable collection of the model aspects definitions, or an empty collection + */ + public Collection getAspectDefinitions(); + + /** + * Returns a {@link Collection} of the model defined {@link ConstraintDefinition}s + * + * @return an unmodifiable collection of the model constraint definitions, or an empty collection + */ + public Collection getModelDefinedConstraints(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelException.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelException.java new file mode 100644 index 0000000000..200bc2bff8 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelException.java @@ -0,0 +1,196 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.service.cmr.dictionary; + +import org.alfresco.error.AlfrescoRuntimeException; + +/** + * @author Jamal Kaabi-Mofrad + */ +public class CustomModelException extends AlfrescoRuntimeException +{ + private static final long serialVersionUID = 2868108814940403250L; + + /** + * Constructor + * + * @param msgId message id + */ + public CustomModelException(String msgId) + { + super(msgId); + } + + /** + * Constructor + * + * @param msgId message id + * @param msgParams message params + */ + public CustomModelException(String msgId, Object[] msgParams) + { + super(msgId, msgParams); + } + + /** + * Constructor + * + * @param msgId message id + * @param cause causing exception + */ + public CustomModelException(String msgId, Throwable cause) + { + super(msgId, cause); + } + + /** + * Constructor + * + * @param msgId message id + * @param msgParams message params + * @param cause causing exception + */ + public CustomModelException(String msgId, Object[] msgParams, Throwable cause) + { + super(msgId, msgParams, cause); + } + + public static class ModelExistsException extends CustomModelException + { + private static final long serialVersionUID = -6092936121754376435L; + + public ModelExistsException(String msgId) + { + super(msgId); + } + + public ModelExistsException(String msgId, Object[] msgParams) + { + super(msgId, msgParams); + } + } + + public static class ModelDoesNotExistException extends CustomModelException + { + private static final long serialVersionUID = 6053078524717867514L; + + public ModelDoesNotExistException(String msgId) + { + super(msgId); + } + + public ModelDoesNotExistException(String msgId, Object[] msgParams) + { + super(msgId, msgParams); + } + } + + public static class InvalidNamespaceException extends CustomModelException + { + private static final long serialVersionUID = 1405352431422776830L; + + public InvalidNamespaceException(String msgId) + { + super(msgId); + } + + public InvalidNamespaceException(String msgId, Object[] msgParams) + { + super(msgId, msgParams); + } + } + + public static class InvalidCustomModelException extends CustomModelException + { + private static final long serialVersionUID = -2450003245810515336L; + + public InvalidCustomModelException(String msgId) + { + super(msgId); + } + + public InvalidCustomModelException(String msgId, Object[] msgParams) + { + super(msgId, msgParams); + } + + public InvalidCustomModelException(String msgId, Throwable cause) + { + super(msgId, cause); + } + + public InvalidCustomModelException(String msgId, Object[] msgParams, Throwable cause) + { + super(msgId, msgParams, cause); + } + } + + public static class CustomModelConstraintException extends CustomModelException + { + private static final long serialVersionUID = 5993485961751086115L; + + public CustomModelConstraintException(String msgId) + { + super(msgId); + } + + public CustomModelConstraintException(String msgId, Object[] msgParams) + { + super(msgId, msgParams); + } + } + + public static class NamespaceConstraintException extends CustomModelConstraintException + { + private static final long serialVersionUID = 9050315122661406808L; + + public NamespaceConstraintException(String msgId) + { + super(msgId); + } + + public NamespaceConstraintException(String msgId, Object[] msgParams) + { + super(msgId, msgParams); + } + } + + public static class ActiveModelConstraintException extends CustomModelConstraintException + { + private static final long serialVersionUID = -6740246156929572802L; + + public ActiveModelConstraintException(String msgId) + { + super(msgId); + } + + public ActiveModelConstraintException(String msgId, Object[] msgParams) + { + super(msgId, msgParams); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelService.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelService.java new file mode 100644 index 0000000000..f1864b2c14 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/CustomModelService.java @@ -0,0 +1,224 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.service.cmr.dictionary; + +import org.alfresco.query.PagingRequest; +import org.alfresco.query.PagingResults; +import org.alfresco.repo.dictionary.CompiledModel; +import org.alfresco.repo.dictionary.CustomModelsInfo; +import org.alfresco.repo.dictionary.M2Model; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; + +/** + * Custom model service configuration API. + * + * @author Jamal Kaabi-Mofrad + */ +public interface CustomModelService +{ + /** + * Gets custom model + * + * @param modelFileName the name of the custom model to retrieve + * @return the {@code CustomModelDefinition} (or null, if it doesn't exist) + */ + public CustomModelDefinition getCustomModel(String modelFileName); + + /** + * Gets custom model + * + * @param namespaceUri the namespace URI defined within the model + * @return the {@code ModelDefinition} (or null, if it doesn't exist) + */ + public ModelDefinition getCustomModelByUri(String namespaceUri); + + /** + * Gets a paged list of custom models + * + * @param pagingRequest paging request + * @return paged list of {@code CustomModelDefinition} + */ + public PagingResults getCustomModels(PagingRequest pagingRequest); + + /** + * Gets custom aspect + * + * @param name the name of the custom aspect to retrieve + * @return the {@code AspectDefinition} (or null, if it doesn't exist) + */ + public AspectDefinition getCustomAspect(QName name); + + /** + * Get a paged list of custom aspects + * + * @param pagingRequest paging request + * @return paged list of {@code AspectDefinition} + */ + public PagingResults getAllCustomAspects(PagingRequest pagingRequest); + + /** + * Gets custom type + * + * @param name the name of the custom type to retrieve + * @return the {@code TypeDefinition} (or null, if it doesn't exist) + */ + public TypeDefinition getCustomType(QName name); + + /** + * Gets a paged list of custom types + * + * @param pagingRequest paging request + * @return paged list of {@code TypeDefinition} + */ + public PagingResults getAllCustomTypes(PagingRequest pagingRequest); + + /** + * Gets custom model node reference + * + * @param modelFileName the name of the custom model to retrieve + * @return the {@code NodeRef} of the custom model (or null, if it doesn't exist) + */ + public NodeRef getModelNodeRef(String modelFileName); + + /** + * Creates custom model + * + * @param m2Model the {@code M2Model} object + * @param activate whether the model should be activated or not + * @return the created model definition as a {@code CustomModelDefinition} object + */ + public CustomModelDefinition createCustomModel(M2Model m2Model, boolean activate); + + /** + * Indicates whether the specified user is a model-administrator or not. + *

+ * Note: The super/repo admin is considered to be a model-administrator too. + * + * @param userName The user name + * @return true if the specified user is a model-administrator, false otherwise + */ + public boolean isModelAdmin(String userName); + + /** + * Activates custom model + * @see {@link org.alfresco.service.cmr.admin.RepoAdminService#activateModel(String)} + * + * @param modelFileName the name of the custom model + */ + public void activateCustomModel(String modelFileName); + + /** + * Deactivates custom model + * @see {@link org.alfresco.service.cmr.admin.RepoAdminService#deactivateModel(String)} + * + * @param modelFileName the name of the custom model + */ + public void deactivateCustomModel(String modelFileName); + + /** + * Updates custom model + * + * @param modelFileName the model name + * @param m2Model the {@code M2Model} object + * @param activate whether the model should be activated or not + * @return the updated model definition as a {@code CustomModelDefinition} object + */ + public CustomModelDefinition updateCustomModel(String modelFileName, M2Model m2Model, boolean activate); + + /** + * Deletes custom model. + *

+ * The model can only be deleted if it is inactive + * + * @param modelFileName the model name + */ + public void deleteCustomModel(String modelFileName); + + /** + * Whether the given URI has already been used or not + * + * @param modelNamespaceUri the model namespace URI + * @return true if the URI has been used, false otherwise + */ + public boolean isNamespaceUriExists(String modelNamespaceUri); + + /** + * Whether a model with the given name exists or not + * + * @param modelFileName the model name + * @return true if the model exists, false otherwise + */ + public boolean isModelExists(String modelFileName); + + /** + * Whether the given namespace prefix has already been used or not + * + * @param modelNamespaceUri the model namespace prefix + * @return true if the prefix has been used, false otherwise + */ + public boolean isNamespacePrefixExists(String modelNamespacePrefix); + + /** + * Gets custom constraint + * + * @param name the name of the custom constraint to retrieve + * @return the {@code ConstraintDefinition} (or null, if it doesn't exist) + */ + public ConstraintDefinition getCustomConstraint(QName name); + + /** + * Creates a downloadable archive file containing the custom model file and + * if specified, its associated Share extension module file. + * + * @param modelName the model name to be exported + * @param withAssociatedForm whether Share extension module file should be + * included or not + * @return reference to the node which will contain the archive file + */ + public NodeRef createDownloadNode(String modelName, boolean withAssociatedForm); + + /** + * Compiles the {@link M2Model}. + * + * @param m2Model the model + * @return the compiled model of the given m2model + * @throws CustomModelConstraintException + * @throws InvalidCustomModelException + */ + public CompiledModel compileModel(M2Model m2Model); + + /** + * Gets custom models' information. + * + * @return {@code CustomModelsInfo} containing: + *

  • number of active models
  • + *
  • number of active models' types
  • + *
  • number of active models' aspects
  • + */ + public CustomModelsInfo getCustomModelsInfo(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/DataTypeDefinition.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/DataTypeDefinition.java new file mode 100644 index 0000000000..98bfdd8692 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/DataTypeDefinition.java @@ -0,0 +1,130 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import java.util.Locale; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + + +/** + * Read-only definition of a Data Type + * + * @author David Caruana + */ +@AlfrescoPublicApi +public interface DataTypeDefinition +{ + // + // Built-in Property Types + // + public QName ANY = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "any"); + public QName ENCRYPTED = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "encrypted"); + public QName TEXT = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "text"); + public QName MLTEXT = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "mltext"); + public QName CONTENT = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "content"); + public QName INT = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "int"); + public QName LONG = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "long"); + public QName FLOAT = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "float"); + public QName DOUBLE = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "double"); + public QName DATE = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "date"); + public QName DATETIME = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "datetime"); + public QName BOOLEAN = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "boolean"); + public QName QNAME = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "qname"); + public QName CATEGORY = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "category"); + public QName NODE_REF = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "noderef"); + public QName CHILD_ASSOC_REF = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "childassocref"); + public QName ASSOC_REF = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "assocref"); + public QName PATH = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "path"); + public QName LOCALE = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "locale"); + public QName PERIOD = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "period"); + + + /** + * @return defining model + */ + public ModelDefinition getModel(); + + /** + * @return the qualified name of the data type + */ + public QName getName(); + + /** + * @deprecated The problem identified in MNT-413 will still exist + * @see org.alfresco.service.cmr.dictionary.DataTypeDefinition#getTitle(org.alfresco.service.cmr.i18n.MessageLookup) + */ + public String getTitle(); + + /** + * @deprecated The problem identified in MNT-413 will still exist + * @see org.alfresco.service.cmr.dictionary.DataTypeDefinition#getDescription(org.alfresco.service.cmr.i18n.MessageLookup) + */ + public String getDescription(); + + /** + * @return the human-readable class title + */ + public String getTitle(MessageLookup messageLookup); + + /** + * @return the human-readable class description + */ + public String getDescription(MessageLookup messageLookup); + + /** + * Get the name of the property bundle that defines analyser mappings for this data type (keyed by the type of the property) + * @return the resource or null if not set. + */ + public String getAnalyserResourceBundleName(); + + /** + * @return the equivalent java class name (or null, if not mapped) + */ + public String getJavaClassName(); + + /** + * Get the default analyser class - used when no resource bundles can be found and no repository default is set. + * @return String + */ + public String getDefaultAnalyserClassName(); + + /** + * @param locale + * @return String + */ + public String resolveAnalyserClassName(Locale locale); + + /** + * + * @return String + */ + public String resolveAnalyserClassName(); + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/DictionaryException.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/DictionaryException.java new file mode 100644 index 0000000000..28f4ee4232 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/DictionaryException.java @@ -0,0 +1,92 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.error.AlfrescoRuntimeException; + +/** + * Base Exception of Data Dictionary Exceptions. + * + * @author David Caruana + */ +@AlfrescoPublicApi +public class DictionaryException extends AlfrescoRuntimeException +{ + private static final long serialVersionUID = 3257008761007847733L; + + public DictionaryException(String msgId) + { + super(msgId); + } + + public DictionaryException(String msgId, Throwable cause) + { + super(msgId, cause); + } + + public DictionaryException(String msgId, Object ... args) + { + super(msgId, args); + } + + public DictionaryException(String msgId, Throwable cause, Object ... args) + { + super(msgId, args, cause); + } + + /** + * Exception generated by attempting to create a duplicate definition of the + * data dictionary, such as type, aspect, constraint and etc. + * + * @author Jamal Kaabi-Mofrad + */ + @AlfrescoPublicApi + public static class DuplicateDefinitionException extends DictionaryException + { + private static final long serialVersionUID = -2623179649246011966L; + + public DuplicateDefinitionException(String msgId) + { + super(msgId); + } + + public DuplicateDefinitionException(String msgId, Throwable cause) + { + super(msgId, cause); + } + + public DuplicateDefinitionException(String msgId, Object... args) + { + super(msgId, args); + } + + public DuplicateDefinitionException(String msgId, Throwable cause, Object... args) + { + super(msgId, cause, args); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/DictionaryService.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/DictionaryService.java new file mode 100644 index 0000000000..4cf0bea6aa --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/DictionaryService.java @@ -0,0 +1,321 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import java.util.Collection; +import java.util.Map; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.NotAuditable; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.QName; + + +/** + * This interface represents the Repository Data Dictionary. The + * dictionary provides access to content meta-data such as Type + * and Aspect descriptions. + *

    + * Content meta-data is organised into models where each model is + * given a qualified name. This means that it is safe to develop + * independent models and bring them together into the same + * Repository without name clashes (as long their namespace is + * different). + * + * @author David Caruana + */ +@AlfrescoPublicApi +public interface DictionaryService extends MessageLookup +{ + + /** + * @return the names of all models that have been registered with the Repository + */ + @NotAuditable + public Collection getAllModels(); + + /** + * @param model the model name to retrieve + * @return the specified model (never null) + * @throws DictionaryException if the model could not be found + */ + @NotAuditable + public ModelDefinition getModel(QName model); + + /** + * @return the names of all data types that have been registered with the Repository + */ + @NotAuditable + Collection getAllDataTypes(); + + /** + * @param model the model to retrieve data types for + * @return the names of all data types defined within the specified model + */ + @NotAuditable + Collection getDataTypes(QName model); + + /** + * @param name the name of the data type to retrieve + * @return the data type definition (or null, if it doesn't exist) + */ + @NotAuditable + DataTypeDefinition getDataType(QName name); + + /** + * @param javaClass java class to find datatype for + * @return the data type definition (or null, if a mapping does not exist) + */ + @NotAuditable + DataTypeDefinition getDataType(Class javaClass); + + /** + * @return the names of all types that have been registered with the Repository + */ + @NotAuditable + Collection getAllTypes(); + + @NotAuditable + Collection getAllTypes(boolean includeInherited); + + /** + * Get the sub types of the type. The returned list includes the base type which is passed in as a parameter. + * + * @param type the qualified name of the type + * @param follow true => all sub-type descendants, false => immediate sub-type children + * @return the names of the sub types of the specified type, including the value passed in. + */ + @NotAuditable + Collection getSubTypes(QName type, boolean follow); + + /** + * @param model the model to retrieve types for + * @return the names of all types defined within the specified model + */ + @NotAuditable + Collection getTypes(QName model); + + /** + * @param name the name of the type to retrieve + * @return the type definition (or null, if it doesn't exist) + */ + @NotAuditable + TypeDefinition getType(QName name); + + /** + * Construct an anonymous type that combines the definitions of the specified + * type and aspects. + * + * @param type the type to start with + * @param aspects the aspects to combine with the type + * @return the anonymous type definition + */ + @NotAuditable + TypeDefinition getAnonymousType(QName type, Collection aspects); + + /** + * Creates an anonymous {@link TypeDefinition} with all the mandatory {@link Aspect Aspects} applied. + * This collapses all mandatory {@link Aspect Aspects} into a single {@link TypeDefinition}. + * + * @param name the name of the type definition. + * @return the anonymous type definition + */ + TypeDefinition getAnonymousType(QName name); + + /** + * @return the names of all aspects that have been registered with the Repository + */ + @NotAuditable + Collection getAllAspects(); + + @NotAuditable + Collection getAllAspects(boolean includeInherited); + + /** + * @param aspect QName + * @param follow true => follow up the super-class hierarchy, false => immediate sub aspects only + * @return the sub aspects of specified aspect + */ + @NotAuditable + Collection getSubAspects(QName aspect, boolean follow); + + /** + * @param model the model to retrieve aspects for + * @return the names of all aspects defined within the specified model + */ + @NotAuditable + Collection getAspects(QName model); + + /** + * @param model the model to retrieve associations for + * @return the names of all associations defined within the specified model + */ + @NotAuditable + public Collection getAssociations(QName model); + + /** + * @param name the name of the aspect to retrieve + * @return the aspect definition (or null, if it doesn't exist) + */ + @NotAuditable + AspectDefinition getAspect(QName name); + + /** + * @param name the name of the class (type or aspect) to retrieve + * @return the class definition (or null, if it doesn't exist) + */ + @NotAuditable + ClassDefinition getClass(QName name); + + /** + * Determines whether a class is a sub-class of another class + * + * @param className the sub-class to test + * @param ofClassName the class to test against + * @return true => the class is a sub-class (or itself) + */ + @NotAuditable + boolean isSubClass(QName className, QName ofClassName); + + /** + * Gets the definition of the property as defined by the specified Class. + * + * Note: A sub-class may override the definition of a property that's + * defined in a super-class. + * + * @param className the class name + * @param propertyName the property name + * @return the property definition (or null, if it doesn't exist) + */ + @NotAuditable + PropertyDefinition getProperty(QName className, QName propertyName); + + /** + * Gets the definitions of the properties defined by the specified Class. + * + * @param className the class name + * @return the property definitions + */ + @NotAuditable + Map getPropertyDefs(QName className); + + /** + * Gets the definition of the property as defined by its owning Class. + * + * @param propertyName the property name + * @return the property definition (or null, if it doesn't exist) + */ + @NotAuditable + PropertyDefinition getProperty(QName propertyName); + + /** + * Get all properties defined across all models with the given data type. + * + * Note that DataTypeDefinition.ANY will only match this type and can not be used as get all properties. + * + * If dataType is null then this method will return *ALL* properties regardless of data type. + * + * @param dataType QName + */ + @NotAuditable + Collection getAllProperties(QName dataType); + + /** + * Get all properties defined for the given model with the given data type. + * + * Note that DataTypeDefinition.ANY will only match this type and can not be used as get all properties. + * + * If dataType is null then this method will return *ALL* properties regardless of data type. + * + * @param model QName + * @param dataType QName + */ + @NotAuditable + Collection getProperties(QName model, QName dataType); + + /** + * Get all properties for the specified model + * + * @param model QName + */ + Collection getProperties(QName model); + + /** + * Gets the definition of the association as defined by its owning Class. + * + * @param associationName the property name + * @return the association definition (or null, if it doesn't exist) + */ + @NotAuditable + AssociationDefinition getAssociation(QName associationName); + + /** + * Get all the association definitions + + * @return all the association qnames + */ + @NotAuditable + Collection getAllAssociations(); + + @NotAuditable + Collection getAllAssociations(boolean includeInherited); + + /** + * Gets the definition of the constraint + * + * @param constraintQName the constraint name + * @return the constraint definition (or null, if it doesn't exist) + * + * @since 3.2.1 + */ + @NotAuditable + public ConstraintDefinition getConstraint(QName constraintQName); + + /** + * Get constraints for the specified model + * + * @param model QName + */ + public Collection getConstraints(QName model); + + /** + * Get constraints for the specified model + + * Optionally return referenceable (ie. non-property specific) constraints only + * + * @param model QName + * @param referenceableDefsOnly boolean + * + * @since 3.2R + */ + Collection getConstraints(QName model, boolean referenceableDefsOnly); + + /** + * @param uri the namespace uri for search for + * @return the named model definition + */ + ModelDefinition getModelByNamespaceUri(String uri); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/InvalidAspectException.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/InvalidAspectException.java new file mode 100644 index 0000000000..8b7a447f8e --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/InvalidAspectException.java @@ -0,0 +1,58 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.namespace.QName; + +/** + * Thrown when a reference to an aspect is incorrect. + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public class InvalidAspectException extends InvalidClassException +{ + private static final long serialVersionUID = 3257290240330051893L; + + public InvalidAspectException(QName aspectName) + { + super(null, aspectName); + } + + public InvalidAspectException(String msg, QName aspectName) + { + super(msg, aspectName); + } + + /** + * @return Returns the offending aspect name + */ + public QName getAspectName() + { + return getClassName(); + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/InvalidClassException.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/InvalidClassException.java new file mode 100644 index 0000000000..f8d3184a67 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/InvalidClassException.java @@ -0,0 +1,60 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.service.namespace.QName; + +/** + * Thrown when an operation cannot be performed because the dictionary class + * reference does not exist. + * + */ +public class InvalidClassException extends AlfrescoRuntimeException +{ + private static final long serialVersionUID = 3256722870754293558L; + + private QName className; + + public InvalidClassException(QName className) + { + this(null, className); + } + + public InvalidClassException(String msg, QName className) + { + super(msg); + this.className = className; + } + + /** + * @return Returns the offending class name + */ + public QName getClassName() + { + return className; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/InvalidTypeException.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/InvalidTypeException.java new file mode 100644 index 0000000000..ecc39ec779 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/InvalidTypeException.java @@ -0,0 +1,59 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.namespace.QName; + +/** + * Thrown when an operation cannot be performed because a type is not recognised + * by the data dictionary + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public class InvalidTypeException extends InvalidClassException +{ + private static final long serialVersionUID = 3256722870754293558L; + + public InvalidTypeException(QName typeName) + { + super("Invalid type: " + typeName, typeName); + } + + public InvalidTypeException(String msg, QName typeName) + { + super(msg, typeName); + } + + /** + * @return Returns the offending type name + */ + public QName getTypeName() + { + return getClassName(); + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ModelDefinition.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ModelDefinition.java new file mode 100644 index 0000000000..01ea8ca9e5 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/ModelDefinition.java @@ -0,0 +1,118 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import java.io.OutputStream; +import java.util.Collection; +import java.util.Date; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.repo.dictionary.DictionaryDAO; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.QName; + + +/** + * Read-only definition of a Model. + * + * @author David Caruana + */ +@AlfrescoPublicApi +public interface ModelDefinition +{ + public static enum XMLBindingType + { + DEFAULT + { + public String toString() + { + return "default"; + } + } + }; + + /** + * @return the model name + */ + public QName getName(); + + /** + * @return the model description + */ + public String getDescription(MessageLookup messageLookup); + + /** + * @return the model author + */ + public String getAuthor(); + + /** + * @return the date when the model was published + */ + public Date getPublishedDate(); + + /** + * @return the model version + */ + public String getVersion(); + + /** + * @return the namespaces defined by this model + */ + public Collection getNamespaces(); + + /** + * @param uri namespace uri + * @return true => model defines the uri + */ + public boolean isNamespaceDefined(String uri); + + /** + * @return the namespaces imported by this model + */ + public Collection getImportedNamespaces(); + + /** + * @param uri namespace uri + * @return true => model imports the uri + */ + public boolean isNamespaceImported(String uri); + + public void toXML(XMLBindingType bindingType, OutputStream xml); + + public long getChecksum(XMLBindingType bindingType); + + /** + * Get the name of the property bundle that defines analyser mappings for this model (keyed by the type of the property) + * @return the resource or null if not set. + */ + public String getAnalyserResourceBundleName(); + + /** + * @return DictionaryDAO + */ + public DictionaryDAO getDictionaryDAO(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/NamespaceDefinition.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/NamespaceDefinition.java new file mode 100644 index 0000000000..ca27ed2293 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/NamespaceDefinition.java @@ -0,0 +1,51 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Read-only definition of a Namespace. + * + */ +@AlfrescoPublicApi +public interface NamespaceDefinition +{ + /** + * @return defining model + */ + public ModelDefinition getModel(); + + /** + * @return the namespace URI + */ + public String getUri(); + + /** + * @return the namespace Prefix + */ + public String getPrefix(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/PropertyDefinition.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/PropertyDefinition.java new file mode 100644 index 0000000000..7d44f8e370 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/PropertyDefinition.java @@ -0,0 +1,182 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.service.cmr.dictionary; + +import java.util.List; +import java.util.Locale; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.repo.dictionary.Facetable; +import org.alfresco.repo.dictionary.IndexTokenisationMode; +import org.alfresco.service.cmr.i18n.MessageLookup; +import org.alfresco.service.namespace.QName; + +/** + * Read-only definition of a Property. + * + * @author David Caruana + */ +@AlfrescoPublicApi +public interface PropertyDefinition extends ClassAttributeDefinition +{ + /** + * @return defining model + */ + public ModelDefinition getModel(); + + /** + * @return the qualified name of the property + */ + public QName getName(); + + /** + * @deprecated The problem identified in MNT-413 will still exist + */ + public String getTitle(); + + /** + * @deprecated The problem identified in MNT-413 will still exist + */ + public String getDescription(); + + /** + * @return the human-readable class title + */ + public String getTitle(MessageLookup messageLookup); + + /** + * @return the human-readable class title in the specified Locale, if available. + * @since 5.0 + */ + public String getTitle(MessageLookup messageLookup, Locale locale); + + /** + * @return the human-readable class description + */ + public String getDescription(MessageLookup messageLookup); + + /** + * @return the human-readable class description in the specified Locale, if available. + * @since 5.0 + */ + public String getDescription(MessageLookup messageLookup, Locale locale); + + /** + * @return the default value + */ + public String getDefaultValue(); + + /** + * @return the qualified name of the property type + */ + public DataTypeDefinition getDataType(); + + /** + * @return Returns the owning class's defintion + */ + public ClassDefinition getContainerClass(); + + public boolean isOverride(); + + /** + * @return true => multi-valued, false => single-valued + */ + public boolean isMultiValued(); + + /** + * @return true => mandatory, false => optional + */ + public boolean isMandatory(); + + /** + * @return Returns true if the system enforces the presence of + * {@link #isMandatory() mandatory} properties, or false if the + * system just marks objects that don't have all mandatory + * properties present. + */ + public boolean isMandatoryEnforced(); + + /** + * @return true => system maintained, false => client may maintain + */ + public boolean isProtected(); + + /** + * @return true => indexed, false => not indexed + */ + public boolean isIndexed(); + + /** + * @return true => stored in index + */ + public boolean isStoredInIndex(); + + /** + * @return IndexTokenisationMode.TREU => tokenised when it is indexed (the + * stored value will not be tokenised) + */ + public IndexTokenisationMode getIndexTokenisationMode(); + + /** + * @return if this field shoul be faceted + */ + public Facetable getFacetable(); + + /** + * All non atomic properties will be indexed at the same time. + * + * @return true => The attribute must be indexed in the commit of the + * transaction. false => the indexing will be done in the background + * and may be out of date. + */ + public boolean isIndexedAtomically(); + + /** + * Get all constraints that apply to the property value + * + * @return Returns a list of property constraint definitions + */ + public List getConstraints(); + + /** + * Get the name of the property bundle that defines analyser mappings for this class. + * @return the resource or null if not set. + */ + public String getAnalyserResourceBundleName(); + + /** + * @param locale Locale + * @return String + */ + public String resolveAnalyserClassName(Locale locale); + + /** + * + * @return String + */ + public String resolveAnalyserClassName(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/dictionary/TypeDefinition.java b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/TypeDefinition.java new file mode 100644 index 0000000000..9e2fc91305 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/dictionary/TypeDefinition.java @@ -0,0 +1,40 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.dictionary; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Read-only definition of a Type + * + * @author David Caruana + */ +@AlfrescoPublicApi +public interface TypeDefinition extends ClassDefinition +{ + + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/i18n/MessageLookup.java b/data-model/src/main/java/org/alfresco/service/cmr/i18n/MessageLookup.java new file mode 100644 index 0000000000..ce9d19f2f7 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/i18n/MessageLookup.java @@ -0,0 +1,86 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.i18n; + +import java.util.Locale; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.NotAuditable; + +/** + * An object providing basic message lookup facilities. May (or may not) be directly conntect to resource bundles. + */ +@AlfrescoPublicApi +public interface MessageLookup +{ + /** + * Get message from registered resource bundle. + * + * @param messageKey + * message key + * @return localised message string, null if not found + */ + @NotAuditable + public String getMessage(String messageKey); + + /** + * Get a localised message string + * + * @param messageKey + * the message key + * @param locale + * override the current locale + * @return the localised message string, null if not found + */ + @NotAuditable + public String getMessage(final String messageKey, final Locale locale); + + /** + * Get a localised message string, parameterized using standard MessageFormatter. + * + * @param messageKey + * message key + * @param params + * format parameters + * @return the localised string, null if not found + */ + @NotAuditable + public String getMessage(String messageKey, Object... params); + + /** + * Get a localised message string, parameterized using standard MessageFormatter. + * + * @param messageKey + * the message key + * @param locale + * override current locale + * @param params + * the localised message string + * @return the localised string, null if not found + */ + @NotAuditable + public String getMessage(String messageKey, Locale locale, Object... params); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/AbstractStoreException.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/AbstractStoreException.java new file mode 100644 index 0000000000..5f4ebc1b04 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/AbstractStoreException.java @@ -0,0 +1,70 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Store-related exception that keeps a handle to the store reference + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public abstract class AbstractStoreException extends RuntimeException +{ + private static final long serialVersionUID = 1315634811903555316L; + + private StoreRef storeRef; + + public AbstractStoreException(StoreRef storeRef) + { + this(null, storeRef, null); + } + + public AbstractStoreException(String msg, StoreRef storeRef) + { + this(msg, storeRef, null); + } + + public AbstractStoreException(StoreRef storeRef, Throwable e) + { + this(null, storeRef, e); + } + + public AbstractStoreException(String msg, StoreRef storeRef, Throwable e) + { + super(msg, e); + this.storeRef = storeRef; + } + + /** + * @return Returns the offending store reference + */ + public StoreRef getStoreRef() + { + return storeRef; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/AssociationExistsException.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/AssociationExistsException.java new file mode 100644 index 0000000000..cdba07bbfc --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/AssociationExistsException.java @@ -0,0 +1,85 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.namespace.QName; + +/** + * Thrown when an operation could not be performed because a named association already + * exists between two nodes + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public class AssociationExistsException extends RuntimeException +{ + private static final long serialVersionUID = 3256440317824874800L; + + private Long sourceNodeId; + private Long targetNodeId; + private QName qname; + + /** + * @see #AssociationExistsException(Long, Long, org.alfresco.service.namespace.QName, Throwable) + */ + public AssociationExistsException(Long sourceNodeId, Long targetNodeId, QName qname) + { + super(); + this.sourceNodeId = sourceNodeId; + this.targetNodeId = targetNodeId; + this.qname = qname; + } + + /** + * @param sourceNodeId the source of the association + * @param targetNodeId the target of the association + * @param qname the qualified name of the association + * @param cause a causal exception + */ + public AssociationExistsException(Long sourceNodeId, Long targetNodeId, QName qname, Throwable cause) + { + super(cause); + this.sourceNodeId = sourceNodeId; + this.targetNodeId = targetNodeId; + this.qname = qname; + } + + public Long getSourceNodeId() + { + return sourceNodeId; + } + + public Long getTargetNodeId() + { + return targetNodeId; + } + + public QName getQName() + { + return qname; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/AssociationRef.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/AssociationRef.java new file mode 100644 index 0000000000..30f07b1d97 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/AssociationRef.java @@ -0,0 +1,213 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.io.Serializable; +import java.util.StringTokenizer; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.EqualsHelper; + +/** + * This class represents a regular, named node relationship between two nodes. + *

    + * Note that the ID of the association might not be populated. + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public class AssociationRef implements EntityRef, Serializable +{ + private static final long serialVersionUID = 3977867284482439475L; + + private static final String FILLER = "|"; + + private Long id; + private NodeRef sourceRef; + private QName assocTypeQName; + private NodeRef targetRef; + + /** + * Construct a representation of a source --- name ----> target relationship. + * + * @param sourceRef + * the source reference - never null + * @param assocTypeQName + * the qualified name of the association type - never null + * @param targetRef + * the target node reference - never null. + */ + public AssociationRef(NodeRef sourceRef, QName assocTypeQName, NodeRef targetRef) + { + this(null, sourceRef, assocTypeQName, targetRef); + } + + /** + * Construct a representation of a source --- name ----> target relationship. + * + * @param id + * unique identifier - may be null + * @param sourceRef + * the source reference - never null + * @param assocTypeQName + * the qualified name of the association type - never null + * @param targetRef + * the target node reference - never null. + */ + public AssociationRef(Long id, NodeRef sourceRef, QName assocTypeQName, NodeRef targetRef) + { + this.id = id; + this.sourceRef = sourceRef; + this.assocTypeQName = assocTypeQName; + this.targetRef = targetRef; + + // check + if (sourceRef == null) + { + throw new IllegalArgumentException("Source reference may not be null"); + } + if (assocTypeQName == null) + { + throw new IllegalArgumentException("QName may not be null"); + } + if (targetRef == null) + { + throw new IllegalArgumentException("Target reference may not be null"); + } + } + + /** + * @param assocRefStr a string of the form id|sourceNodeRef|targetNodeRef|assocTypeQName. + */ + public AssociationRef(String assocRefStr) + { + StringTokenizer tokenizer = new StringTokenizer(assocRefStr, FILLER); + if (tokenizer.countTokens() != 3 && tokenizer.countTokens() != 4) + { + throw new AlfrescoRuntimeException("Unable to parse association string: " + assocRefStr); + } + + String idStr = "0"; + if (tokenizer.countTokens() == 4) + { + idStr = tokenizer.nextToken(); + } + String sourceNodeRefStr = tokenizer.nextToken(); + String targetNodeRefStr = tokenizer.nextToken(); + String assocTypeQNameStr = tokenizer.nextToken(); + + this.id = new Long(idStr); + this.sourceRef = new NodeRef(sourceNodeRefStr); + this.targetRef = new NodeRef(targetNodeRefStr); + this.assocTypeQName = QName.createQName(assocTypeQNameStr); + } + + /** + * @return Returns a string of the form sourceNodeRef|targetNodeRef|assocTypeQName|assocQName + */ + public String toString() + { + StringBuilder sb = new StringBuilder(180); + sb.append(id == null ? Long.valueOf(0) : id).append(FILLER) + .append(sourceRef).append(FILLER) + .append(targetRef).append(FILLER) + .append(assocTypeQName); + return sb.toString(); + } + + /** + * Compares: + *

      + *
    • {@link #sourceRef}
    • + *
    • {@link #targetRef}
    • + *
    • {@link #assocTypeQName}
    • + *
    + */ + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof AssociationRef)) + { + return false; + } + AssociationRef other = (AssociationRef) o; + + return (EqualsHelper.nullSafeEquals(this.sourceRef, other.sourceRef) + && EqualsHelper.nullSafeEquals(this.assocTypeQName, other.assocTypeQName) + && EqualsHelper.nullSafeEquals(this.targetRef, other.targetRef)); + } + + public int hashCode() + { + int hashCode = ((getSourceRef() == null) ? 0 : getSourceRef().hashCode()); + hashCode = 37 * hashCode + ((getTypeQName() == null) ? 0 : getTypeQName().hashCode()); + hashCode = 37 * hashCode + getTargetRef().hashCode(); + return hashCode; + } + + /** + * Gets the unique identifier for this association. + * + * @return the unique identifier for this association, or null if the ID was not + * given at the time of construction + */ + public Long getId() + { + return this.id; + } + + /** + * Get the qualified name of the source-target association + * + * @return Returns the qualified name of the source-target association. + */ + public QName getTypeQName() + { + return assocTypeQName; + } + + /** + * @return Returns the child node reference - never null + */ + public NodeRef getTargetRef() + { + return targetRef; + } + + /** + * @return Returns the parent node reference, which may be null if this + * represents the imaginary reference to the root node + */ + public NodeRef getSourceRef() + { + return sourceRef; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/ChildAssociationRef.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/ChildAssociationRef.java new file mode 100644 index 0000000000..7183cf6bbd --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/ChildAssociationRef.java @@ -0,0 +1,273 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.io.Serializable; +import java.util.StringTokenizer; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.EqualsHelper; + +/** + * This class represents a child relationship between two nodes. This + * relationship is named. + *

    + * So it requires the parent node ref, the child node ref and the name of the + * child within the particular parent. + *

    + * This combination is not a unique identifier for the relationship with regard + * to structure. In use this does not matter as we have no concept of order, + * particularly in the index. + * + * @author andyh + * + */ +@AlfrescoPublicApi +public class ChildAssociationRef + implements EntityRef, Comparable, Serializable +{ + private static final long serialVersionUID = 4051322336257127729L; + + private static final String FILLER = "|"; + + private QName assocTypeQName; + private NodeRef parentRef; + private QName childQName; + private NodeRef childRef; + private boolean isPrimary; + private int nthSibling; + + + /** + * Construct a representation of a parent --- name ----> child relationship. + * + * @param assocTypeQName + * the type of the association + * @param parentRef + * the parent reference - may be null + * @param childQName + * the qualified name of the association - may be null + * @param childRef + * the child node reference. This must not be null. + * @param isPrimary + * true if this represents the primary parent-child relationship + * @param nthSibling + * the nth association with the same properties. Usually -1 to be + * ignored. + */ + public ChildAssociationRef( + QName assocTypeQName, + NodeRef parentRef, + QName childQName, + NodeRef childRef, + boolean isPrimary, + int nthSibling) + { + this.assocTypeQName = assocTypeQName; + this.parentRef = parentRef; + this.childQName = childQName; + this.childRef = childRef; + this.isPrimary = isPrimary; + this.nthSibling = nthSibling; + + // check + if (childRef == null) + { + throw new IllegalArgumentException("Child reference may not be null"); + } + } + + /** + * Constructs a non-primary, -1th sibling parent-child association + * reference. + * + * @see ChildAssociationRef#ChildAssociationRef(org.alfresco.service.namespace.QName, NodeRef, org.alfresco.service.namespace.QName, NodeRef) + */ + public ChildAssociationRef(QName assocTypeQName, NodeRef parentRef, QName childQName, NodeRef childRef) + { + this(assocTypeQName, parentRef, childQName, childRef, false, -1); + } + + /** + * @param childAssocRefStr a string of the form parentNodeRef|childNodeRef|assocTypeQName|assocQName|isPrimary|nthSibling + */ + public ChildAssociationRef(String childAssocRefStr) + { + StringTokenizer tokenizer = new StringTokenizer(childAssocRefStr, FILLER); + if (tokenizer.countTokens() != 6) + { + throw new AlfrescoRuntimeException("Unable to parse child association string: " + childAssocRefStr); + } + String parentNodeRefStr = tokenizer.nextToken(); + String childNodeRefStr = tokenizer.nextToken(); + String assocTypeQNameStr = tokenizer.nextToken(); + String assocQNameStr = tokenizer.nextToken(); + String isPrimaryStr = tokenizer.nextToken(); + String nthSiblingStr = tokenizer.nextToken(); + + this.parentRef = new NodeRef(parentNodeRefStr); + this.childRef = new NodeRef(childNodeRefStr); + this.assocTypeQName = QName.createQName(assocTypeQNameStr); + this.childQName = QName.createQName(assocQNameStr); + this.isPrimary = Boolean.parseBoolean(isPrimaryStr); + this.nthSibling = Integer.parseInt(nthSiblingStr); + } + + /** + * @return Returns a string of the form parentNodeRef|childNodeRef|assocTypeQName|assocQName|isPrimary|nthSibling + */ + public String toString() + { + StringBuilder sb = new StringBuilder(250); + sb.append(parentRef).append(FILLER) + .append(childRef).append(FILLER) + .append(assocTypeQName).append(FILLER) + .append(childQName).append(FILLER) + .append(isPrimary).append(FILLER) + .append(nthSibling); + return sb.toString(); + } + + /** + * Compares: + *

      + *
    • {@link #assocTypeQName}
    • + *
    • {@link #parentRef}
    • + *
    • {@link #childRef}
    • + *
    • {@link #childQName}
    • + *
    + */ + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (!(o instanceof ChildAssociationRef)) + { + return false; + } + ChildAssociationRef other = (ChildAssociationRef) o; + + return (EqualsHelper.nullSafeEquals(this.assocTypeQName, other.assocTypeQName) + && EqualsHelper.nullSafeEquals(this.parentRef, other.parentRef) + && EqualsHelper.nullSafeEquals(this.childQName, other.childQName) + && EqualsHelper.nullSafeEquals(this.childRef, other.childRef)); + } + + public int hashCode() + { + int hashCode = ((getTypeQName() == null) ? 0 : getTypeQName().hashCode()); + hashCode = 37 * hashCode + ((getParentRef() == null) ? 0 : getParentRef().hashCode()); + hashCode = 37 * hashCode + ((getQName() == null) ? 0 : getQName().hashCode()); + hashCode = 37 * hashCode + getChildRef().hashCode(); + return hashCode; + } + + /** + * @see #setNthSibling(int) + */ + public int compareTo(ChildAssociationRef another) + { + int thisVal = this.nthSibling; + int anotherVal = another.nthSibling; + return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); + } + + /** + * Get the qualified name of the association type + * + * @return Returns the qualified name of the parent-child association type + * as defined in the data dictionary. It may be null if this is the + * imaginary association to the root node. + */ + public QName getTypeQName() + { + return assocTypeQName; + } + + /** + * Get the qualified name of the parent-child association + * + * @return Returns the qualified name of the parent-child association. It + * may be null if this is the imaginary association to a root node. + */ + public QName getQName() + { + return childQName; + } + + /** + * @return Returns the child node reference - never null + */ + public NodeRef getChildRef() + { + return childRef; + } + + /** + * @return Returns the parent node reference, which may be null if this + * represents the imaginary reference to the root node + */ + public NodeRef getParentRef() + { + return parentRef; + } + + /** + * @return Returns true if this represents a primary association + */ + public boolean isPrimary() + { + return isPrimary; + } + + /** + * @return Returns the nth sibling required + */ + public int getNthSibling() + { + return nthSibling; + } + + /** + * Allows post-creation setting of the ordering index. This is a helper + * so that sorted sets and lists can be easily sorted. + *

    + * This index is in no way absolute and should change depending on + * the results that appear around this instance. Therefore, the sibling + * number cannot be used to construct, say, sibling number 5. Sibling + * number 5 will exist only in results where there are siblings 1 - 4. + * + * @param nthSibling the sibling index + */ + public void setNthSibling(int nthSibling) + { + this.nthSibling = nthSibling; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentAccessor.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentAccessor.java new file mode 100644 index 0000000000..21051b42a6 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentAccessor.java @@ -0,0 +1,140 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.util.Locale; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Interface for instances that provide read and write access to content. + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public interface ContentAccessor +{ + /** + * Gets the open/close state of the underlying IO Channel. + * + * @return Returns true if the underlying IO Channel is open + */ + public boolean isChannelOpen(); + + /** + * Use this method to register any interest in events against underlying + * content streams. + *

    + * This method can only be used before the content stream has been retrieved. + *

    + * When the stream has been closed, all listeners will be called. + * The listener is responsible for using a retrying transaction to protect the implementation of the callback when required. + * + * @param listener a listener that will be called for output stream + * event notification + * + */ + public void addListener(ContentStreamListener listener); + + + /** + * Gets the size of the content that this reader references. + * + * @return Returns the document byte length, or OL if the + * content doesn't exist. + */ + public long getSize(); + + /** + * Get the data representation of the content being accessed. + *

    + * The content {@link #setMimetype(String) mimetype } must be set before this + * method is called as the content data requires a mimetype whenever the + * content URL is specified. + * + * @return Returns the content data + * + * @see ContentData#ContentData(String, String, long, String) + */ + public ContentData getContentData(); + + /** + * Retrieve the URL that this accessor references + * + * @return the content URL + */ + public String getContentUrl(); + + /** + * Get the content mimetype + * + * @return Returns a content mimetype + */ + public String getMimetype(); + + /** + * Set the mimetype that must be used for accessing the content. + *

    + * When dealing with a {@link ContentWriter}, you may wish + * to use {@link ContentWriter#guessMimetype(String)} to have + * this set for you based on the filename and contents. + * + * @param mimetype the content mimetype + */ + public void setMimetype(String mimetype); + + /** + * Get the encoding of the content being accessed + * + * @return Returns a valid java String encoding + */ + public String getEncoding(); + + /** + * Set the String encoding for this accessor + *

    + * When dealing with a {@link ContentWriter}, you may wish + * to use {@link ContentWriter#guessMimetype(String)} to have + * this set for you based on the contents. + * + * @param encoding a java-recognised encoding format + */ + public void setEncoding(String encoding); + + /** + * Get the locale of the content being accessed + * + * @return Returns a valid java Locale + */ + public Locale getLocale(); + + /** + * Set the Locale for this accessor + * + * @param locale a java-recognised locale + */ + public void setLocale(Locale locale); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentData.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentData.java new file mode 100644 index 0000000000..3db7a1c528 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentData.java @@ -0,0 +1,379 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.io.Serializable; +import java.util.Locale; +import java.util.StringTokenizer; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.util.EqualsHelper; +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * The compound property representing content + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public class ContentData implements Serializable +{ + private static final long serialVersionUID = 8979634213050121462L; + + private static char[] INVALID_CONTENT_URL_CHARS = new char[] {'|'}; + + private final String contentUrl; + private final String mimetype; + private final long size; + private final String encoding; + private final Locale locale; + + /** + * Construct a content property from a string + * + * @param contentPropertyStr the string representing the content details + * @return Returns a bean version of the string + */ + public static ContentData createContentProperty(String contentPropertyStr) + { + String contentUrl = null; + String mimetype = null; + long size = 0L; + String encoding = null; + Locale locale = null; + // now parse the string + StringTokenizer tokenizer = new StringTokenizer(contentPropertyStr, "|"); + while (tokenizer.hasMoreTokens()) + { + String token = tokenizer.nextToken(); + if (token.startsWith("contentUrl=")) + { + contentUrl = token.substring(11); + if (contentUrl.length() == 0) + { + contentUrl = null; + } + } + else if (token.startsWith("mimetype=")) + { + mimetype = token.substring(9); + if (mimetype.length() == 0) + { + mimetype = null; + } + } + else if (token.startsWith("size=")) + { + String sizeStr = token.substring(5); + if (sizeStr.length() > 0) + { + size = Long.parseLong(sizeStr); + } + } + else if (token.startsWith("encoding=")) + { + encoding = token.substring(9); + if (encoding.length() == 0) + { + encoding = null; + } + } + else if (token.startsWith("locale=")) + { + String localeStr = token.substring(7); + if (localeStr.length() > 0) + { + locale = I18NUtil.parseLocale(localeStr); + } + } + } + + ContentData property = new ContentData(contentUrl, mimetype, size, encoding, locale); + // done + return property; + } + + /** + * Constructs a new instance using the existing one as a template, but replacing the + * mimetype + * + * @param existing an existing set of content data, null to use default values + * @param mimetype the mimetype to set + * @return Returns a new, immutable instance of the data + */ + public static ContentData setMimetype(ContentData existing, String mimetype) + { + ContentData ret = new ContentData( + existing == null ? null : existing.contentUrl, + mimetype, + existing == null ? 0L : existing.size, + existing == null ? "UTF-8" : existing.encoding, + existing == null ? null : existing.locale); + // done + return ret; + } + + /** + * Constructs a new instance using the existing one as a template, but replacing the + * encoding. + * + * @param existing an existing set of content data, null to use default values + * @param encoding the encoding to set + * @return Returns a new, immutable instance of the data + */ + public static ContentData setEncoding(ContentData existing, String encoding) + { + ContentData ret = new ContentData( + existing == null ? null : existing.contentUrl, + existing == null ? null : existing.mimetype, + existing == null ? 0L : existing.size, + encoding, + existing == null ? null : existing.locale); + // done + return ret; + } + + /** + * Helper method to determine if the data represents any physical content or not. + *

    + * This method only cares if there is a binary (content URL) and makes no assumptions + * about the length of the binary. + * + * @param contentData the content to check (may be null) + * @return true if the content URL is non-null i.e. there is a binary available + */ + public static boolean hasContent(ContentData contentData) + { + if (contentData == null) + { + return false; + } + return contentData.contentUrl != null; + } + + /** + * Copy constructor for derived class + * + * @param original the object to copy + */ + protected ContentData(ContentData original) + { + this.contentUrl = original.contentUrl; + this.encoding = original.encoding; + this.locale = original.locale; + this.mimetype = original.mimetype; + this.size = original.size; + } + + /** + * Create a content data using the {@link I18NUtil#getLocale() default locale}. + * + * @see #ContentData(String, String, long, String, Locale) + */ + public ContentData(String contentUrl, String mimetype, long size, String encoding) + { + this(contentUrl, mimetype, size, encoding, null); + } + + /** + * Create a compound set of data representing a single instance of content. + *

    + * In order to ensure data integrity, the {@link #getMimetype() mimetype} + * must be set if the {@link #getContentUrl() content URL} is set. + * + * @param contentUrl the content URL. If this value is non-null, then the + * mimetype must be supplied. + * @param mimetype the content mimetype. This is mandatory if the contentUrl is specified. + * @param size the content size. + * @param encoding the content encoding. This is mandatory if the contentUrl is specified. + * @param locale the locale of the content (may be null). If null, the + * {@link I18NUtil#getLocale() default locale} will be used. + */ + public ContentData(String contentUrl, String mimetype, long size, String encoding, Locale locale) + { + if (contentUrl != null && (mimetype == null || mimetype.length() == 0)) + { + mimetype = MimetypeMap.MIMETYPE_BINARY; + } + checkContentUrl(contentUrl, mimetype, encoding); + this.contentUrl = contentUrl; + this.mimetype = mimetype; + this.size = size; + this.encoding = encoding; + if (locale == null) + { + locale = I18NUtil.getLocale(); + } + this.locale = locale; + } + + public boolean equals(Object obj) + { + if (obj == this) + return true; + else if (obj == null) + return false; + else if (!(obj instanceof ContentData)) + return false; + ContentData that = (ContentData) obj; + return (EqualsHelper.nullSafeEquals(this.contentUrl, that.contentUrl) && + EqualsHelper.nullSafeEquals(this.mimetype, that.mimetype, true) && + this.size == that.size && + EqualsHelper.nullSafeEquals(this.encoding, that.encoding, true) && + EqualsHelper.nullSafeEquals(this.locale, that.locale)); + } + + /** + * @return Returns a string of form: contentUrl=xxx|mimetype=xxx|size=xxx|encoding=xxx|locale=xxx + */ + public String toString() + { + return getInfoUrl(); + } + + /** + * @return Returns a URL containing information on the content including the mimetype, + * locale, encoding and size, the string is returned in the form: + * contentUrl=xxx|mimetype=xxx|size=xxx|encoding=xxx|locale=xxx + */ + public String getInfoUrl() + { + StringBuilder sb = new StringBuilder(80); + sb.append("contentUrl=").append(contentUrl == null ? "" : contentUrl) + .append("|mimetype=").append(mimetype == null ? "" : mimetype) + .append("|size=").append(size) + .append("|encoding=").append(encoding == null ? "" : encoding) + .append("|locale=").append(locale == null ? "" : DefaultTypeConverter.INSTANCE.convert(String.class, locale)); + return sb.toString(); + } + + /** + * @return Returns a URL identifying the specific location of the content. + * The URL must identify, within the context of the originating content + * store, the exact location of the content. + * @throws ContentIOException + */ + public String getContentUrl() + { + return contentUrl; + } + + /** + * Checks that the content URL is correct, and also that the mimetype is + * non-null if the URL is present. + * + * @param contentUrl the content URL to check + * @param mimetype the encoding must be present if the content URL is present + * @param encoding the encoding must be valid and present if the content URL is present + */ + private void checkContentUrl(String contentUrl, String mimetype, String encoding) + { + // check the URL + if (contentUrl != null && contentUrl.length() > 0) + { + for (int i = 0; i < INVALID_CONTENT_URL_CHARS.length; i++) + { + for (int j = contentUrl.length() - 1; j > -1; j--) + { + if (contentUrl.charAt(j) == INVALID_CONTENT_URL_CHARS[i]) + { + throw new IllegalArgumentException( + "The content URL contains an invalid char: \n" + + " content URL: " + contentUrl + "\n" + + " char: " + INVALID_CONTENT_URL_CHARS[i] + "\n" + + " position: " + j); + } + } + } + + // check that mimetype is present if URL is present + if (mimetype == null) + { + throw new IllegalArgumentException("\n" + + "The content mimetype must be set whenever the URL is set: \n" + + " content URL: " + contentUrl + "\n" + + " and mimetype cannot be 'null'."); + } + } + } + + /** + * Gets content's mimetype. + * + * @return Returns a standard mimetype for the content or null if the mimetype + * is unkown + */ + public String getMimetype() + { + return mimetype; + } + + /** + * Get the content's size + * + * @return Returns the size of the content + */ + public long getSize() + { + return size; + } + + /** + * Gets the content's encoding. + * + * @return Returns a valid Java encoding, typically a character encoding, or + * null if the encoding is unkown + */ + public String getEncoding() + { + return encoding; + } + + /** + * Get the content's locale. + * + * @return Returns a locale, or null if the locale is unknown + */ + public Locale getLocale() + { + return locale; + } + + /** + * @return hashCode + */ + public int hashCode() + { + if(contentUrl!= null) + { + return contentUrl.hashCode(); + } + return 0; + } +} + diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentIOException.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentIOException.java new file mode 100644 index 0000000000..2135a3194e --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentIOException.java @@ -0,0 +1,54 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.error.AlfrescoRuntimeException; + + +/** + * Wraps a general Exceptions that occurred while reading or writing + * content. + * + * @see Throwable#getCause() + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public class ContentIOException extends AlfrescoRuntimeException +{ + private static final long serialVersionUID = 3258130249983276087L; + + public ContentIOException(String msg) + { + super(msg); + } + + public ContentIOException(String msg, Throwable cause) + { + super(msg, cause); + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentReader.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentReader.java new file mode 100644 index 0000000000..330ce9c1d3 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentReader.java @@ -0,0 +1,194 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Represents a handle to read specific content. Content may only be accessed + * once per instance. + *

    + * Implementations of this interface might be Serializable + * but client code could should check suitability before attempting to serialize + * it. + *

    + * Implementations that are able to provide inter-VM streaming, such as accessing + * WebDAV, would be Serializable. An accessor that has to access a + * local file on the server could not provide inter-VM streaming unless it specifically + * makes remote calls and opens sockets, etc. + * + * @see org.alfresco.service.cmr.repository.ContentWriter + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public interface ContentReader extends ContentAccessor +{ + /** + * Convenience method to get another reader onto the underlying content. + * + * @return Returns a reader onto the underlying content + * @throws ContentIOException + */ + public ContentReader getReader() throws ContentIOException; + + /** + * Check if the {@link ContentAccessor#getContentUrl() underlying content} is present. + * + * @return Returns true if there is content at the URL refered to by this reader + */ + public boolean exists(); + + /** + * Gets the time of the last modification of the underlying content. + * + * @return Returns the last modification time using the standard long + * time, or 0L if the content doesn't {@link #exists() exist}. + * + * @see System#currentTimeMillis() + */ + public long getLastModified(); + + /** + * Convenience method to find out if this reader has been closed. + * Once closed, the content can no longer be read. This method could + * be used to wait for a particular read operation to complete, for example. + * + * @return Return true if the content input stream has been used and closed + * otherwise false. + */ + public boolean isClosed(); + + /** + * Provides low-level access to the underlying content. + *

    + * Once the stream is provided to a client it should remain active + * (subject to any timeouts) until closed by the client. + * + * @return Returns a stream that can be read at will, but must be closed when completed + * @throws ContentIOException + */ + public ReadableByteChannel getReadableChannel() throws ContentIOException; + + /** + * Provides read-only, random-access to the underlying content. In general, this method + * should be considered more expensive than the sequential-access method, + * {@link #getReadableChannel()}. + * + * @return Returns a random-access channel onto the content + * @throws ContentIOException + * + * @see #getReadableChannel() + * @see java.io.RandomAccessFile#getChannel() + */ + public FileChannel getFileChannel() throws ContentIOException; + + /** + * Get a stream to read from the underlying channel + * + * @return Returns an input stream onto the underlying channel + * @throws ContentIOException + * + * @see #getReadableChannel() + */ + public InputStream getContentInputStream() throws ContentIOException; + + /** + * Gets content from the repository. + *

    + * All resources will be closed automatically. + *

    + * Care must be taken that the bytes read from the stream are properly + * decoded according to the {@link ContentAccessor#getEncoding() encoding} + * property. + * + * @param os the stream to which to write the content + * @throws ContentIOException + * + * @see #getReadableChannel() + */ + public void getContent(OutputStream os) throws ContentIOException; + + /** + * Gets content from the repository direct to file + *

    + * All resources will be closed automatically. + * + * @param file the file to write the content to - it will be overwritten + * @throws ContentIOException + * + * @see #getContentInputStream() + */ + public void getContent(File file) throws ContentIOException; + + /** + * Gets content from the repository direct to String. + *

    + * If the {@link ContentAccessor#getEncoding() encoding } is known then it will be used + * otherwise the default system byte[] to String conversion + * will be used. + *

    + * All resources will be closed automatically. + *

    + * WARNING: This should only be used when the size of the content + * is known in advance. + * + * @return Returns a String representation of the content + * @throws ContentIOException + * + * @see #getContentString(int) + * @see #getContentInputStream() + * @see String#String(byte[]) + */ + public String getContentString() throws ContentIOException; + + /** + * Gets content from the repository direct to String, but limiting + * the string size to a given number of characters. + *

    + * If the {@link ContentAccessor#getEncoding() encoding } is known then it will be used + * otherwise the default system byte[] to String conversion + * will be used. + *

    + * All resources will be closed automatically. + * + * @param length the maximum number of characters to retrieve + * @return Returns a truncated String representation of the content + * @throws ContentIOException + * @throws java.lang.IllegalArgumentException if the length is < 0 or > {@link Integer#MAX_VALUE} + * + * @see #getContentString() + * @see #getContentInputStream() + * @see String#String(byte[]) + */ + public String getContentString(int length) throws ContentIOException; +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentServiceTransientException.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentServiceTransientException.java new file mode 100644 index 0000000000..e6ced0455b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentServiceTransientException.java @@ -0,0 +1,56 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * This exception should be thrown when a content operation could not be performed due to + * a transient condition and where it is possible that a subsequent request to execute the + * same action might succeed, all other things not having changed. + *

    + * An example of this would be the case where a request to create a thumbnail + * has failed because the necessary thumbnailing software is not available e.g. because the OpenOffice.org process + * is not currently running. + * + * @author Neil Mc Erlean + * @since 4.0.1 + */ +@AlfrescoPublicApi +public class ContentServiceTransientException extends ContentIOException +{ + private static final long serialVersionUID = 3258130249983276087L; + + public ContentServiceTransientException(String msg) + { + super(msg); + } + + public ContentServiceTransientException(String msg, Throwable cause) + { + super(msg, cause); + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentStreamListener.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentStreamListener.java new file mode 100644 index 0000000000..c90c997853 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentStreamListener.java @@ -0,0 +1,45 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Listens for notifications w.r.t. content. This includes receiving notifications + * of the opening and closing of the content streams. + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public interface ContentStreamListener +{ + /** + * Called when the stream associated with a reader or writer is closed + * + * @throws ContentIOException + */ + public void contentStreamClosed() throws ContentIOException; +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentUrlKey.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentUrlKey.java new file mode 100644 index 0000000000..8f9230e6c6 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentUrlKey.java @@ -0,0 +1,110 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.io.Serializable; +import java.nio.ByteBuffer; + +/** + * + * @author sglover + * + */ +public class ContentUrlKey implements Serializable +{ + private static final long serialVersionUID = -2943112451758281764L; + + private ByteBuffer encryptedKeyBytes; + private Integer keySize; + private String algorithm; + private String masterKeystoreId; + private String masterKeyAlias; + private Long unencryptedFileSize; + + public ContentUrlKey() + { + } + + public ByteBuffer getEncryptedKeyBytes() + { + return encryptedKeyBytes; + } + + public void setEncryptedKeyBytes(ByteBuffer encryptedKeyBytes) + { + this.encryptedKeyBytes = encryptedKeyBytes; + } + + public Long getUnencryptedFileSize() + { + return unencryptedFileSize; + } + + public void setUnencryptedFileSize(Long unencryptedFileSize) + { + this.unencryptedFileSize = unencryptedFileSize; + } + + public void setKeySize(Integer keySize) + { + this.keySize = keySize; + } + + public Integer getKeySize() + { + return keySize; + } + + public String getAlgorithm() + { + return algorithm; + } + + public void setAlgorithm(String algorithm) + { + this.algorithm = algorithm; + } + + public String getMasterKeystoreId() + { + return masterKeystoreId; + } + + public void setMasterKeystoreId(String masterKeystoreId) + { + this.masterKeystoreId = masterKeystoreId; + } + + public String getMasterKeyAlias() + { + return masterKeyAlias; + } + + public void setMasterKeyAlias(String masterKeyAlias) + { + this.masterKeyAlias = masterKeyAlias; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentWriter.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentWriter.java new file mode 100644 index 0000000000..621daf98fb --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/ContentWriter.java @@ -0,0 +1,195 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.channels.FileChannel; +import java.nio.channels.WritableByteChannel; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Represents a handle to write specific content. Content may only be accessed + * once per instance. + *

    + * Implementations of this interface might be Serializable + * but client code could should check suitability before attempting to serialize + * it. + *

    + * Implementations that are able to provide inter-VM streaming, such as accessing + * WebDAV, would be Serializable. An accessor that has to access a + * local file on the server could not provide inter-VM streaming unless it specifically + * makes remote calls and opens sockets, etc. + * + * @see org.alfresco.service.cmr.repository.ContentReader + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public interface ContentWriter extends ContentAccessor +{ + /** + * Convenience method to get a reader onto newly written content. This + * method will return null if the content has not yet been written by the + * writer or if the output stream is still open. + * + * @return Returns a reader onto the underlying content that this writer + * will or has written to + * @throws ContentIOException + */ + public ContentReader getReader() throws ContentIOException; + + /** + * Convenience method to find out if this writer has been closed. + * Once closed, the content can no longer be written to and it become possible + * to get readers onto the written content. + * + * @return Return true if the content output stream has been used and closed + * otherwise false. + */ + public boolean isClosed(); + + /** + * Provides low-level access to write to repository content. + *

    + * The channel returned to the client should remain open (subject to timeouts) + * until closed by the client. All lock detection, read-only access and other + * concurrency issues are dealt with during this operation. It remains + * possible that implementations will throw exceptions when the channel is closed. + *

    + * The stream will notify any listeners according to the listener interface. + * + * @return Returns a channel with which to write content + * @throws ContentIOException + */ + public WritableByteChannel getWritableChannel() throws ContentIOException; + + /** + * Provides read-write, random-access to the underlying content. In general, this method + * should be considered more expensive than the sequential-access method, + * {@link #getWritableChannel()}. + *

    + * Underlying implementations use the truncate parameter to determine the + * most effective means of providing access to the content. + * + * @param truncate true to start with zero length content + * @return Returns a random-access channel onto the content + * @throws ContentIOException + * + * @see #getWritableChannel() + * @see java.io.RandomAccessFile#getChannel() + */ + public FileChannel getFileChannel(boolean truncate) throws ContentIOException; + + /** + * Get a stream to write to the underlying channel. + * + * @return Returns an output stream onto the underlying channel + * @throws ContentIOException + * + * @see #getWritableChannel() + */ + public OutputStream getContentOutputStream() throws ContentIOException; + + /** + * Copies content from the reader. + *

    + * All resources will be closed automatically. + * + * @param reader the reader acting as the source of the content + * @throws ContentIOException + * + * @see #getWritableChannel() + */ + public void putContent(ContentReader reader) throws ContentIOException; + + /** + * Puts content to the repository + *

    + * All resources will be closed automatically. + * + * @param is the input stream from which the content will be read + * @throws ContentIOException + * + * @see #getWritableChannel() + */ + public void putContent(InputStream is) throws ContentIOException; + + /** + * Puts content to the repository direct from file + *

    + * All resources will be closed automatically. + * + * @param file the file to load the content from + * @throws ContentIOException + * + * @see #getWritableChannel() + */ + public void putContent(File file) throws ContentIOException; + + /** + * Puts content to the repository direct from String. + *

    + * If the {@link ContentAccessor#getEncoding() encoding } is known then it will be used + * otherwise the default system String to byte[] conversion + * will be used. + *

    + * All resources will be closed automatically. + * + * @param content a string representation of the content + * @throws ContentIOException + * + * @see #getWritableChannel() + * @see String#getBytes(java.lang.String) + */ + public void putContent(String content) throws ContentIOException; + + /** + * Attempts to guess the mimetype of the Content based on + * the contents and the filename. + *

    + * If the content has already been written, then the mimetype + * guessing will occur immediately. If the content has yet + * to be written, then the guessing will occur once the + * content write has completed. + * + * @param filename The filename of the content (if known) + */ + public void guessMimetype(String filename); + + /** + * Attempts to guess the encoding of the Content based on + * the contents. + *

    + * If the content has already been written, then the encoding + * guessing will occur immediately. If the content has yet + * to be written, then the guessing will occur once the + * content write has completed. + */ + public void guessEncoding(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/EntityRef.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/EntityRef.java new file mode 100644 index 0000000000..12475bef80 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/EntityRef.java @@ -0,0 +1,45 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.io.Serializable; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * A marker interface for entity reference classes. + *

    + * This is used primarily as a means of ensuring type safety in collections + * of mixed type references. + * + * @see org.alfresco.service.cmr.repository.NodeService#removeChild(NodeRef, NodeRef) + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public interface EntityRef extends Serializable +{ +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/FileContentReader.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/FileContentReader.java new file mode 100644 index 0000000000..f3b8b39cfc --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/FileContentReader.java @@ -0,0 +1,52 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.io.File; + +/** + * Extension to {@link ContentReader} for Readers which are able to + * make the backing file available to you. + * + * @see org.alfresco.service.cmr.repository.ContentReader + * + * @author Derek Hulley + */ +public interface FileContentReader extends ContentReader +{ + /** + * Provides access to the underlying File that this + * Reader accesses. + * + * @return Returns the file that this reader accesses + */ + public File getFile(); + + /** + * @return Whether the file exists or not + */ + public boolean exists(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/InvalidChildAssociationRefException.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/InvalidChildAssociationRefException.java new file mode 100644 index 0000000000..2b1066ba05 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/InvalidChildAssociationRefException.java @@ -0,0 +1,58 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +/** + * Thrown when an operation cannot be performed because thechild association + * reference no longer exists. + * + * @author Derek Hulley + */ +public class InvalidChildAssociationRefException extends RuntimeException +{ + private static final long serialVersionUID = -7493054268618534572L; + + private ChildAssociationRef childAssociationRef; + + public InvalidChildAssociationRefException(ChildAssociationRef childAssociationRef) + { + this(null, childAssociationRef); + } + + public InvalidChildAssociationRefException(String msg, ChildAssociationRef childAssociationRef) + { + super(msg); + this.childAssociationRef = childAssociationRef; + } + + /** + * @return Returns the offending child association reference + */ + public ChildAssociationRef getChildAssociationRef() + { + return childAssociationRef; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/InvalidNodeRefException.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/InvalidNodeRefException.java new file mode 100644 index 0000000000..e79fc36af7 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/InvalidNodeRefException.java @@ -0,0 +1,66 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Thrown when an operation cannot be performed because the node reference + * no longer exists. + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public class InvalidNodeRefException extends RuntimeException +{ + private static final long serialVersionUID = 3689345520586273336L; + + private NodeRef nodeRef; + + public InvalidNodeRefException(NodeRef nodeRef) + { + this(null, nodeRef); + } + + public InvalidNodeRefException(String msg, NodeRef nodeRef) + { + this(msg, nodeRef, null); + } + + public InvalidNodeRefException(String msg, NodeRef nodeRef, Throwable cause) + { + super(msg, cause); + this.nodeRef = nodeRef; + } + + /** + * @return Returns the offending node reference + */ + public NodeRef getNodeRef() + { + return nodeRef; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/InvalidStoreRefException.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/InvalidStoreRefException.java new file mode 100644 index 0000000000..82a4201f1a --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/InvalidStoreRefException.java @@ -0,0 +1,50 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Thrown when an operation cannot be performed because the store reference + * no longer exists. + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public class InvalidStoreRefException extends AbstractStoreException +{ + private static final long serialVersionUID = 3258126938479409463L; + + public InvalidStoreRefException(StoreRef storeRef) + { + this("Invalid store: " + storeRef, storeRef); + } + + public InvalidStoreRefException(String msg, StoreRef storeRef) + { + super(msg, storeRef); + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/MLText.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/MLText.java new file mode 100644 index 0000000000..7825628f38 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/MLText.java @@ -0,0 +1,200 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Locale; +import java.util.Set; + +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * Class to represent a multilingual (ML) text value. + *

    + * The language codes used should conform to the + * ISO639-2 + * language code standard, although there is no enforcement of the standard in this + * class. + *

    + * This is a simple extension of a HashMap with a few convenience methods. + * + * @see ISO639-2 + * + * @author Philippe Dubois + * @author Derek Hulley + */ +public class MLText extends HashMap +{ + private static final long serialVersionUID = -3696135175650511841L; + + public MLText() + { + super(3, 0.75F); + } + + /** + * Construct an instance with a value corresponding to the current context locale. + * + * @param value the value for the current default locale + * + * @see I18NUtil#getLocale() + * @see #MLText(Locale, String) + * @see #getDefaultValue() + */ + public MLText(String value) + { + this(I18NUtil.getLocale(), value); + } + + /** + * Construct an instance with a value for the given locale. + * + * @param locale the locale + * @param value the value + * + * @see #getDefaultValue() + */ + public MLText(Locale locale, String value) + { + super(3, 0.75F); + super.put(locale, value); + } + + /** + * @return Returns all the language locales defined in the text + */ + public Set getLocales() + { + return keySet(); + } + + /** + * @return Returns all the values stored + */ + public Collection getValues() + { + return values(); + } + + /** + * Add a multilingual text value + * + * @param locale the language locale + * @param value the multilingual text + */ + public void addValue(Locale locale, String value) + { + put(locale, value); + } + + /** + * Retrieve a multilingual text value + * + * @param locale the language locale + */ + public String getValue(Locale locale) + { + return get(locale); + } + + /** + * Retrieves a default value from the set of available locales.
    + * + * @see I18NUtil#getLocale() + * @see #getClosestValue(Locale) + */ + public String getDefaultValue() + { + // Shortcut so that we don't have to go and get the current locale + if (this.size() == 0) + { + return null; + } + // There is some hope of getting a match + Locale locale = I18NUtil.getLocale(); + return getClosestValue(locale); + } + + /** + * The given locale is used to search for a matching value according to: + *

      + *
    • An exact locale match
    • + *
    • A match of locale ISO language codes
    • + *
    • The value for the locale provided in the {@link MLText#MLText(Locale, String) constructor}
    • + *
    • An arbitrary value
    • + *
    • null
    • + *
    + * + * @param locale the locale to use as the starting point of the value search + * @return Returns a default String value or null if one isn't available. + * null will only be returned if there are no values associated with + * this instance. With or without a match, the return value may be null, + * depending on the values associated with the locales. + */ + public String getClosestValue(Locale locale) + { + if (this.size() == 0) + { + return null; + } + // Use the available keys as options + Set options = keySet(); + // Get a match + Locale match = I18NUtil.getNearestLocale(locale, options); + if (match == null) + { + // No close matches for the locale - go for the default locale + locale = I18NUtil.getLocale(); + match = I18NUtil.getNearestLocale(locale, options); + if (match == null) + { + // just get any locale + match = I18NUtil.getNearestLocale(null, options); + } + } + // Did we get a match + if (match == null) + { + // We could find no locale matches + return null; + } + else + { + return get(match); + } + } + + /** + * Remove a multilingual text value + * + * @param locale the language locale + */ + public void removeValue(Locale locale) + { + remove(locale); + } +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/MalformedNodeRefException.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/MalformedNodeRefException.java new file mode 100644 index 0000000000..138fc331bc --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/MalformedNodeRefException.java @@ -0,0 +1,63 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.error.AlfrescoRuntimeException; + +/** + * Thrown when a nodeRef representation is invalid. + * + * @author rgauss + * + */ +@AlfrescoPublicApi +public class MalformedNodeRefException extends AlfrescoRuntimeException +{ + + private static final long serialVersionUID = 8922346977484016269L; + + public MalformedNodeRefException(String msgId) + { + super(msgId); + } + + public MalformedNodeRefException(String msgId, Object[] msgParams) + { + super(msgId, msgParams); + } + + public MalformedNodeRefException(String msgId, Throwable cause) + { + super(msgId, cause); + } + + public MalformedNodeRefException(String msgId, Object[] msgParams, Throwable cause) + { + super(msgId, msgParams, cause); + } + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/MimetypeService.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/MimetypeService.java new file mode 100644 index 0000000000..c1c03aa3e7 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/MimetypeService.java @@ -0,0 +1,182 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.io.InputStream; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.repo.content.encoding.ContentCharsetFinder; +import org.alfresco.service.NotAuditable; + + +/** + * This service interface provides support for Mimetypes. + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public interface MimetypeService +{ + /** + * Get the extension for the specified mimetype + * + * @param mimetype a valid mimetype + * @return Returns the default extension for the mimetype + */ + @NotAuditable + public String getExtension(String mimetype); + + /** + * Get the mimetype for the specified extension + * + * @param extension a valid file extension + * @return Returns a valid mimetype if found, or null if does not exist + */ + @NotAuditable + public String getMimetype(String extension); + + /** + * Get all human readable mimetype descriptions indexed by mimetype extension + * + * @return the map of displays indexed by extension + */ + @NotAuditable + public Map getDisplaysByExtension(); + + /** + * Get all human readable mimetype descriptions indexed by mimetype + * + * @return the map of displays indexed by mimetype + */ + @NotAuditable + public Map getDisplaysByMimetype(); + + /** + * Get all mimetype extensions indexed by mimetype + * + * @return the map of extension indexed by mimetype + */ + @NotAuditable + public Map getExtensionsByMimetype(); + + /** + * Get all mimetypes indexed by extension + * + * @return the map of mimetypes indexed by extension + */ + @NotAuditable + public Map getMimetypesByExtension(); + + /** + * Check if a given mimetype represents a text format. + * + * @param mimetype the mimetype to check + * @return Returns true if it is text + */ + @NotAuditable + public boolean isText(String mimetype); + + /** + * Get all mimetypes + * + * @return all mimetypes + */ + @NotAuditable + public List getMimetypes(); + + /** + * Provides a non-null best guess of the appropriate mimetype given a + * filename, based entirely on the file extension. Because file + * extensions can be wrong, you are strongly advised to use + * {@link #guessMimetype(String, ContentReader)} instead. + * + * @param filename the name of the file with an optional file extension + * @return Returns the best guess mimetype or the mimetype for + * straight binary files if no extension could be found. + */ + @NotAuditable + public String guessMimetype(String filename); + + /** + * Provides a non-null best guess of the appropriate mimetype for a + * given file. Uses a mixture of file name and file content + * logic to identify the mimetype for the file, and will usually + * manage to identify files with incorrect extensions. + * + * @param filename the name of the file with an optional file extension + * @param reader a reader for the content of the file + * @return Returns the best guess mimetype or the mimetype for + * straight binary files if no extension could be found. + */ + @NotAuditable + public String guessMimetype(String filename, ContentReader reader); + + /** + * Provides a non-null best guess of the appropriate mimetype for a + * given file. Uses a mixture of file name and file content + * logic to identify the mimetype for the file, and will usually + * manage to identify files with incorrect extensions. + * + * @param filename the name of the file with an optional file extension + * @param input an input stream for the content + * @return Returns the best guess mimetype or the mimetype for + * straight binary files if no extension could be found. + */ + @NotAuditable + public String guessMimetype(String filename, InputStream input); + + /** + * Use detection heuristics to check if the mime type of the document really + * matches what it claims to be. + * This is typically used when a transformation or metadata extractions fails, + * and you want to know if someone has renamed a file and consequently it has + * the wrong mime type. + * @return Null if the mime type seems ok, otherwise the mime type it probably is + */ + @NotAuditable + public String getMimetypeIfNotMatches(ContentReader reader); + + /** + * Provides the system default charset finder. + * + * @return Returns a character set finder that can be used to decode + * streams in order to get the encoding. + * + * @since 2.1 + */ + @NotAuditable + public ContentCharsetFinder getContentCharsetFinder(); + + /** + * Returns a collection of mimetypes ordered by extension. + * @param extension to restrict the collection to one entry + */ + @NotAuditable + public Collection getMimetypes(String extension); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/MimetypeServiceAware.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/MimetypeServiceAware.java new file mode 100644 index 0000000000..f65140d16c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/MimetypeServiceAware.java @@ -0,0 +1,36 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +/** + * Consumers of the {@link MimetypeService} should implement this interface. + * + * @author Matt Ward + */ +public interface MimetypeServiceAware +{ + void setMimetypeService(MimetypeService mimetypeService); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/NodeRef.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/NodeRef.java new file mode 100644 index 0000000000..c940359d51 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/NodeRef.java @@ -0,0 +1,311 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.alfresco.api.AlfrescoPublicApi; +import org.apache.commons.logging.Log; + +/** + * Reference to a node + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public final class NodeRef implements EntityRef, Serializable +{ + // Let's force introspection of this class straight away so that we don't get contention when multiple threads try + // to cache BeanInfo + static + { + try + { + Introspector.getBeanInfo(NodeRef.class); + } + catch (IntrospectionException e) + { + throw new ExceptionInInitializerError(e); + } + } + + private static final long serialVersionUID = 3760844584074227768L; + private static final String URI_FILLER = "/"; + private static final Pattern nodeRefPattern = Pattern.compile(".+://.+/.+"); + + private final StoreRef storeRef; + private final String id; + + /** + * @see #NodeRef(StoreRef, String) + * @see StoreRef#StoreRef(String, String) + */ + public NodeRef(String protocol, String identifier, String id) + { + this(new StoreRef(protocol, identifier), id); + } + + /** + * Construct a Node Reference from a Store Reference and Node Id + * + * @param storeRef store reference + * @param id the manually assigned identifier of the node + */ + public NodeRef(StoreRef storeRef, String id) + { + if (storeRef == null) + { + throw new IllegalArgumentException("Store reference may not be null"); + } + if (id == null) + { + throw new IllegalArgumentException("Node id may not be null"); + } + + this.storeRef = storeRef; + this.id = id; + } + + /** + * Construct a Node Reference from a string representation of a Node Reference. + *

    + * The string representation of a Node Reference is as follows: + *

    + *
    /
    + * + * @param nodeRef the string representation of a node ref + */ + public NodeRef(String nodeRef) + { + int lastForwardSlash = nodeRef.lastIndexOf('/'); + if(lastForwardSlash == -1) + { + throw new MalformedNodeRefException("Invalid node ref - does not contain forward slash: " + nodeRef); + } + this.storeRef = new StoreRef(nodeRef.substring(0, lastForwardSlash)); + this.id = nodeRef.substring(lastForwardSlash+1); + } + + @Override + public String toString() + { + return storeRef.toString() + URI_FILLER + id; + } + + /** + * Override equals for this ref type + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj instanceof NodeRef) + { + NodeRef that = (NodeRef) obj; + return (this.id.equals(that.id) + && this.storeRef.equals(that.storeRef)); + } + else + { + return false; + } + } + + /** + * Hashes on ID alone. As the number of copies of a particular node will be minimal, this is acceptable + */ + @Override + public int hashCode() + { + return id.hashCode(); + } + + /** + * @return The StoreRef part of this reference + */ + public final StoreRef getStoreRef() + { + return storeRef; + } + + /** + * @return The Node Id part of this reference + */ + public final String getId() + { + return id; + } + + /** + * Determine if passed string conforms to the pattern of a node reference + * + * @param nodeRef the node reference as a string + * @return true => it matches the pattern of a node reference + */ + public static boolean isNodeRef(String nodeRef) + { + Matcher matcher = nodeRefPattern.matcher(nodeRef); + return matcher.matches(); + } + + /** + * Converts a {@link String} containing a comma-separated list of {@link NodeRef} Ids into NodeRefs. + * @param values the {@link String} of {@link NodeRef} ids. + * @return A {@link List} of {@link NodeRef NodeRefs}. + */ + public static List getNodeRefs(String values) + { + return getNodeRefs(values, null); + } + + /** + * Converts a {@link String} containing a comma-separated list of {@link NodeRef} Ids into NodeRefs. + * If a logger is supplied then invalid ids are logged as warnings. + * @param values the {@link String} of {@link NodeRef} ids. + * @param logger Log + * @return A {@link List} of {@link NodeRef NodeRefs}. + */ + public static List getNodeRefs(String values, Log logger) + { + if(values==null || values.length()==0) + return Collections.emptyList(); + String[] nodeRefIds = values.split(","); + List nodeRefs = new ArrayList(nodeRefIds.length); + for (String nodeRefString : nodeRefIds) + { + String nodeRefId = nodeRefString.trim(); + if (NodeRef.isNodeRef(nodeRefId)) + { + NodeRef nodeRef = new NodeRef(nodeRefId); + nodeRefs.add(nodeRef); + } + else if (logger!=null) + { + logNodeRefError(nodeRefId, logger); + } + } + return nodeRefs; + } + + private static void logNodeRefError(String nodeRefId, Log logger) + { + if (logger.isWarnEnabled()) + { + StringBuilder msg = new StringBuilder(); + msg.append("Target Node: ").append(nodeRefId); + msg.append(" is not a valid NodeRef and has been ignored."); + logger.warn(msg.toString()); + } + } + + /** + * Helper class to convey the status of a node. + * + * @author Derek Hulley + */ + public static class Status + { + private final Long dbId; + private final NodeRef nodeRef; + private final String changeTxnId; + private final Long dbTxnId; + private final boolean deleted; + + public Status(Long dbId, NodeRef nodeRef, String changeTxnId, Long dbTxnId, boolean deleted) + { + this.dbId = dbId; + this.nodeRef = nodeRef; + this.changeTxnId = changeTxnId; + this.dbTxnId = dbTxnId; + this.deleted = deleted; + } + /** + * Return the database ID for the node + */ + public Long getDbId() + { + return dbId; + } + /** + * @return Returns the NodeRef that to which this status applies + */ + public NodeRef getNodeRef() + { + return nodeRef; + } + /** + * @return Returns the ID of the last transaction to change the node + * + * @deprecated This will be removed when we have switched to SOLR tracking only + */ + public String getChangeTxnId() + { + return changeTxnId; + } + /** + * @return Returns the db ID of the last transaction to change the node + */ + public Long getDbTxnId() + { + return dbTxnId; + } + /** + * @return Returns true if the node has been deleted, otherwise false + */ + public boolean isDeleted() + { + return deleted; + } + + // debug display string + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(50); + + sb.append("Status[") + .append("id=").append(dbId) + .append("changeTxnId=").append(changeTxnId) + .append(", dbTxnId=").append(dbTxnId) + .append(", deleted=").append(deleted) + .append("]"); + + return sb.toString(); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/NodeService.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/NodeService.java new file mode 100644 index 0000000000..449b4dad9c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/NodeService.java @@ -0,0 +1,1008 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.Auditable; +import org.alfresco.service.cmr.dictionary.InvalidAspectException; +import org.alfresco.service.cmr.dictionary.InvalidTypeException; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.QNamePattern; +import org.alfresco.service.namespace.RegexQNamePattern; + +/** + * Interface for public and internal node and store operations. + *

    + * Amongst other things, this service must enforce the unique name check as mandated + * by the duplicate entity in the model. + *

    + *    <type name="cm:folder">
    + *       ...
    + *       <associations>
    + *          <child-association name="cm:contains">
    + *             ...
    + *             <duplicate>false</duplicate>
    + *          </child-association>
    + *       </associations>
    + *    </type>
    + * 
    + * When duplicates are not allowed, and the cm:name property of a node changes, + * then the {@link org.alfresco.service.cmr.repository.DuplicateChildNodeNameException} + * exception must be thrown. Client code can catch this exception and deal with it + * appropriately. + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public interface NodeService +{ + /** + * Gets a list of all available node store references + * + * @return Returns a list of store references + */ + @Auditable + public List getStores(); + + /** + * Create a new store for the given protocol and identifier. The implementation + * may create the store in any number of locations, including a database or + * Subversion. + * + * @param protocol implementation protocol + * @param identifier the protocol-specific identifier + * @return Returns a reference to the store + * @throws StoreExistsException + */ + @Auditable(parameters = {"protocol", "identifier"}) + public StoreRef createStore(String protocol, String identifier) throws StoreExistsException; + + /** + * Delete a store and all its contents. + * + * @param storeRef the store to delete + * @throws InvalidStoreRefException if the store reference is invalid + */ + @Auditable(parameters = {"storeRef"}) + public void deleteStore(StoreRef storeRef); + + /** + * @param storeRef a reference to the store to look for + * @return Returns true if the store exists, otherwise false + */ + @Auditable(parameters = {"storeRef"}) + public boolean exists(StoreRef storeRef); + + /** + * @param nodeRef a reference to the node to look for + * @return Returns true if the node exists, otherwise false + */ + @Auditable(parameters = {"nodeRef"}) + public boolean exists(NodeRef nodeRef); + + /** + * Gets the ID of the last transaction that caused the node to change. This includes + * deletions, so it is possible that the node being referenced no longer exists. + * If the node never existed, then null is returned. + * + * @param nodeRef a reference to a current or previously existing node + * @return Returns the status of the node, or null if the node never existed + */ + @Auditable(parameters = {"nodeRef"}) + public NodeRef.Status getNodeStatus(NodeRef nodeRef); + + /** + * Get the node reference for a given node DB ID + * + * @param nodeId the node's DB ID + * @return the corresponding node reference or null if not found + */ + @Auditable(parameters = {"nodeId"}) + public NodeRef getNodeRef(Long nodeId); + + /** + * @param storeRef a reference to an existing store + * @return Returns a reference to the root node of the store + * @throws InvalidStoreRefException if the store could not be found + */ + @Auditable(parameters = {"storeRef"}) + public NodeRef getRootNode(StoreRef storeRef) throws InvalidStoreRefException; + + /** + * @param storeRef a reference to an existing store + * @return Returns a set of references to all nodes in the store tagged with the root aspect + * @throws InvalidStoreRefException if the store could not be found + */ + @Auditable(parameters = {"storeRef"}) + public Set getAllRootNodes(StoreRef storeRef); + + /** + * @see #createNode(NodeRef, QName, QName, QName, Map) + */ + @Auditable(parameters = {"parentRef", "assocTypeQName", "assocQName", "nodeTypeQName"}) + public ChildAssociationRef createNode( + NodeRef parentRef, + QName assocTypeQName, + QName assocQName, + QName nodeTypeQName) + throws InvalidNodeRefException, InvalidTypeException; + + /** + * Creates a new, non-abstract, real node as a primary child of the given parent node. + * + * @param parentRef the parent node + * @param assocTypeQName the type of the association to create. This is used + * for verification against the data dictionary. + * @param assocQName the qualified name of the association + * @param nodeTypeQName a reference to the node type + * @param properties optional map of properties to keyed by their qualified names + * @return Returns a reference to the newly created child association + * @throws InvalidNodeRefException if the parent reference is invalid + * @throws InvalidTypeException if the node type reference is not recognised + * + * @see org.alfresco.service.cmr.dictionary.DictionaryService + */ + @Auditable(parameters = {"parentRef", "assocTypeQName", "assocQName", "nodeTypeQName", "properties"}) + public ChildAssociationRef createNode( + NodeRef parentRef, + QName assocTypeQName, + QName assocQName, + QName nodeTypeQName, + Map properties) + throws InvalidNodeRefException, InvalidTypeException; + + /** + * Moves the primary location of the given node. + *

    + * This involves changing the node's primary parent and possibly the name of the + * association referencing it. + *

    + * If the new parent is in a different store from the original, then the entire + * node hierarchy is moved to the new store. Inter-store associations are not + * affected. + * + * @param nodeToMoveRef the node to move + * @param newParentRef the new parent of the moved node + * @param assocTypeQName the type of the association to create. This is used + * for verification against the data dictionary. + * @param assocQName the qualified name of the new child association + * @return Returns a reference to the newly created child association + * @throws InvalidNodeRefException if either the parent node or move node reference is invalid + * @throws org.alfresco.service.cmr.repository.CyclicChildRelationshipException if the child partakes in a cyclic relationship after the add + * + * @see #getPrimaryParent(NodeRef) + */ + @Auditable(parameters = {"nodeToMoveRef", "newParentRef", "assocTypeQName", "assocQName"}) + public ChildAssociationRef moveNode( + NodeRef nodeToMoveRef, + NodeRef newParentRef, + QName assocTypeQName, + QName assocQName) + throws InvalidNodeRefException; + + /** + * Set the ordering index of the child association. This affects the ordering of + * of the return values of methods that return a set of children or child + * associations. + * + * @param childAssocRef the child association that must be moved in the order + * @param index an arbitrary index that will affect the return order + * + * @see #getChildAssocs(NodeRef) + * @see #getChildAssocs(NodeRef, QNamePattern, QNamePattern) + * @see ChildAssociationRef#getNthSibling() + */ + @Auditable(parameters = {"childAssocRef", "index"}) + public void setChildAssociationIndex( + ChildAssociationRef childAssocRef, + int index) + throws InvalidChildAssociationRefException; + + /** + * @param nodeRef NodeRef + * @return Returns the type name + * @throws InvalidNodeRefException if the node could not be found + * + * @see org.alfresco.service.cmr.dictionary.DictionaryService + */ + @Auditable(parameters = {"nodeRef"}) + public QName getType(NodeRef nodeRef) throws InvalidNodeRefException; + + /** + * Re-sets the type of the node. Can be called in order specialise a node to a sub-type. + * + * This should be used with caution since calling it changes the type of the node and thus + * implies a different set of aspects, properties and associations. It is the calling codes + * responsibility to ensure that the node is in a approriate state after changing the type. + * + * @param nodeRef the node reference + * @param typeQName the type QName + * + * @since 1.1 + */ + @Auditable(parameters = {"nodeRef", "typeQName"}) + public void setType(NodeRef nodeRef, QName typeQName) throws InvalidNodeRefException; + + /** + * Applies an aspect to the given node. After this method has been called, + * the node with have all the aspect-related properties present + * + * @param nodeRef NodeRef + * @param aspectTypeQName the aspect to apply to the node + * @param aspectProperties a minimum of the mandatory properties required for + * the aspect + * @throws InvalidNodeRefException + * @throws InvalidAspectException if the class reference is not to a valid aspect + * + * @see org.alfresco.service.cmr.dictionary.DictionaryService#getAspect(QName) + * @see org.alfresco.service.cmr.dictionary.ClassDefinition#getProperties() + */ + @Auditable(parameters = {"nodeRef", "aspectTypeQName", "aspectProperties"}) + public void addAspect( + NodeRef nodeRef, + QName aspectTypeQName, + Map aspectProperties) + throws InvalidNodeRefException, InvalidAspectException; + + /** + * Remove an aspect and all related properties from a node + * + * @param nodeRef NodeRef + * @param aspectTypeQName the type of aspect to remove + * @throws InvalidNodeRefException if the node could not be found + * @throws InvalidAspectException if the the aspect is unknown or if the + * aspect is mandatory for the class of the node + */ + @Auditable(parameters = {"nodeRef", "aspectTypeQName"}) + public void removeAspect(NodeRef nodeRef, QName aspectTypeQName) + throws InvalidNodeRefException, InvalidAspectException; + + /** + * Determines if a given aspect is present on a node. Aspects may only be + * removed if they are NOT mandatory. + * + * @param nodeRef NodeRef + * @param aspectTypeQName QName + * @return Returns true if the aspect has been applied to the given node, + * otherwise false + * @throws InvalidNodeRefException if the node could not be found + * @throws InvalidAspectException if the aspect reference is invalid + */ + @Auditable(parameters = {"nodeRef", "aspectTypeQName"}) + public boolean hasAspect(NodeRef nodeRef, QName aspectTypeQName) + throws InvalidNodeRefException, InvalidAspectException; + + /** + * @param nodeRef NodeRef + * @return Returns a set of all aspects applied to the node, including mandatory + * aspects + * @throws InvalidNodeRefException if the node could not be found + */ + @Auditable(parameters = {"nodeRef"}) + public Set getAspects(NodeRef nodeRef) throws InvalidNodeRefException; + + /** + * Deletes the given node. + *

    + * All associations (both children and regular node associations) + * will be deleted, and where the given node is the primary parent, + * the children will also be cascade deleted. + *

    + * Node stores may be mapped to an associated archive node store. For example, Alfresco ships with the mapping
    + * {@link StoreRef#STORE_REF_WORKSPACE_SPACESSTORE workspace://SpacesStore} .. maps to .. {@link StoreRef#STORE_REF_ARCHIVE_SPACESSTORE archive://SpacesStore}.
    + * When a node is deleted: + *

      + *
    • If there *is a mapping* from the node's current store to an archive store, the node is first copied to the archive store
    • + *
    • If there *is no mapping* from the node's current store, then the node is permanently deleted
    • + *
    + * When nodes have been archived, they contain all the details of the original location. Use the {@link #restoreNode(NodeRef, NodeRef, QName, QName) restore} + * feature to return a node back to its original store. + * + * @param nodeRef reference to a node within a store + * @throws InvalidNodeRefException if the reference given is invalid + */ + @Auditable(parameters = {"nodeRef"}) + public void deleteNode(NodeRef nodeRef) throws InvalidNodeRefException; + + /** + * Makes a parent-child association between the given nodes. Both nodes must belong to the same store. + * + * @param parentRef the parent node + * @param childRef the child node + * @param assocTypeQName the qualified name of the association type as defined in the datadictionary + * @param qname the qualified name of the association + * @return Returns a reference to the newly created child association + * @throws InvalidNodeRefException if the parent or child nodes could not be found + * @throws org.alfresco.service.cmr.repository.CyclicChildRelationshipException if the child partakes in a cyclic relationship after the add + */ + @Auditable(parameters = {"parentRef", "childRef", "assocTypeQName", "qname"}) + public ChildAssociationRef addChild( + NodeRef parentRef, + NodeRef childRef, + QName assocTypeQName, + QName qname) throws InvalidNodeRefException; + + /** + * Associates a given child node with a given collection of parents. All nodes must belong to the same store. + * + * @param parentRefs the parent nodes (there will be this many associations created). + * @param childRef the child node + * @param assocTypeQName the qualified name of the association type as defined in the datadictionary + * @param qname the qualified name of the association + * @return Returns a reference to the newly created child association + * @throws InvalidNodeRefException if the parent or child nodes could not be found + * @throws org.alfresco.service.cmr.repository.CyclicChildRelationshipException if the child partakes in a cyclic relationship after the add + */ + @Auditable(parameters = {"parentRefs", "childRef", "assocTypeQName", "qname"}) + public List addChild( + Collection parentRefs, + NodeRef childRef, + QName assocTypeQName, + QName qname) throws InvalidNodeRefException; + + /** + * Severs all parent-child relationships between two nodes. + *

    + * The child node will be cascade deleted if one of the associations was the + * primary association, i.e. the one with which the child node was created. + * + * @param parentRef the parent end of the association + * @param childRef the child end of the association + * @throws InvalidNodeRefException if the parent or child nodes could not be found + */ + @Auditable(parameters = {"parentRef", "childRef"}) + public void removeChild(NodeRef parentRef, NodeRef childRef) throws InvalidNodeRefException; + + /** + * Remove a specific child association. + *

    + * The child node will be cascade deleted if the association was the + * primary association, i.e. the one with which the child node was created. + * + * @param childAssocRef the association to remove + * @return Returns true if the association existed, otherwise false. + */ + @Auditable(parameters = {"childAssocRef"}) + public boolean removeChildAssociation(ChildAssociationRef childAssocRef); + + /** + * @deprecated Use {@link #removeSecondaryChildAssociation(ChildAssociationRef)} + */ + @Auditable(parameters = {"childAssocRef"}) + public boolean removeSeconaryChildAssociation(ChildAssociationRef childAssocRef); + + /** + * Remove a specific secondary child association. + * + * @param childAssocRef the association to remove + * @return Returns true if the association existed, otherwise false. + * @throws IllegalArgumentException if the association is primary + * + * @since 4.0 + */ + @Auditable(parameters = {"childAssocRef"}) + public boolean removeSecondaryChildAssociation(ChildAssociationRef childAssocRef); + + /** + * @param nodeRef NodeRef + * @return Returns all properties keyed by their qualified name + * @throws InvalidNodeRefException if the node could not be found + */ + @Auditable(parameters = {"nodeRef"}) + public Map getProperties(NodeRef nodeRef) throws InvalidNodeRefException; + + /** + * @param nodeRef NodeRef + * @return Returns the acl id of the node + * @throws InvalidNodeRefException if the node could not be found + */ + @Auditable(parameters = {"nodeRef"}) + public Long getNodeAclId(NodeRef nodeRef) throws InvalidNodeRefException; + + /** + * @param nodeRef NodeRef + * @param qname the qualified name of the property + * @return Returns the value of the property, or null if not yet set + * @throws InvalidNodeRefException if the node could not be found + */ + @Auditable(parameters = {"nodeRef", "qname"}) + public Serializable getProperty(NodeRef nodeRef, QName qname) throws InvalidNodeRefException; + + /** + * Replace all current properties on the node with the given properties. + * The properties given must still fulfill the requirements of the class and + * aspects relevant to the node. + *

    + * NOTE: Null values are allowed. + * + * @param nodeRef the node to chance + * @param properties all the properties of the node keyed by their qualified names + * @throws InvalidNodeRefException if the node could not be found + */ + @Auditable(parameters = {"nodeRef", "properties"}) + public void setProperties(NodeRef nodeRef, Map properties) throws InvalidNodeRefException; + + /** + * Add all given properties to the node. + *

    + * NOTE: Null values are allowed and will replace the existing value. + * + * @param nodeRef the node to change + * @param properties the properties to change, keyed by their qualified names + * @throws InvalidNodeRefException if the node could not be found + */ + @Auditable(parameters = {"nodeRef", "properties"}) + public void addProperties(NodeRef nodeRef, Map properties) throws InvalidNodeRefException; + + /** + * Sets the value of a property to be any Serializable instance. + *

    + * NOTE: Null values are allowed. + * + * @param nodeRef a reference to an existing node + * @param qname the fully qualified name of the property + * @param value the value of the property - never null + * @throws InvalidNodeRefException if the node could not be found + */ + @Auditable(parameters = {"nodeRef", "qname", "value"}) + public void setProperty(NodeRef nodeRef, QName qname, Serializable value) throws InvalidNodeRefException; + + /** + * Removes a property value completely. + * + * @param nodeRef a reference to an existing node + * @param qname the fully qualified name of the property + * @throws InvalidNodeRefException if the node could not be found + */ + @Auditable(parameters = {"nodeRef", "qname"}) + public void removeProperty(NodeRef nodeRef, QName qname) throws InvalidNodeRefException; + + /** + * @param nodeRef the child node + * @return Returns a list of all parent-child associations that exist where the given + * node is the child + * @throws InvalidNodeRefException if the node could not be found + * + * @see #getParentAssocs(NodeRef, QNamePattern, QNamePattern) + */ + @Auditable(parameters = {"nodeRef"}) + public List getParentAssocs(NodeRef nodeRef) throws InvalidNodeRefException; + + /** + * Gets all parent associations where the pattern of the association qualified + * name is a match + *

    + * The resultant list is ordered by (a) explicit index and (b) association creation time. + * + * @param nodeRef the child node + * @param typeQNamePattern the pattern that the type qualified name of the association must match + * @param qnamePattern the pattern that the qnames of the assocs must match + * @return Returns a list of all parent-child associations that exist where the given + * node is the child + * @throws InvalidNodeRefException if the node could not be found + * + * @see ChildAssociationRef#getNthSibling() + * @see #setChildAssociationIndex(ChildAssociationRef, int) + * @see QName + * @see org.alfresco.service.namespace.RegexQNamePattern#MATCH_ALL + */ + @Auditable(parameters = {"nodeRef", "typeQNamePattern", "qnamePattern"}) + public List getParentAssocs(NodeRef nodeRef, QNamePattern typeQNamePattern, QNamePattern qnamePattern) + throws InvalidNodeRefException; + + /** + * Get all child associations of the given node. + *

    + * The resultant list is ordered by (a) explicit index and (b) association creation time. + * + * @param nodeRef the parent node - usually a container + * @return Returns a collection of ChildAssocRef instances. If the + * node is not a container then the result will be empty. + * @throws InvalidNodeRefException if the node could not be found + * + * @see #getChildAssocs(NodeRef, QNamePattern, QNamePattern) + * @see #setChildAssociationIndex(ChildAssociationRef, int) + * @see ChildAssociationRef#getNthSibling() + */ + @Auditable(parameters = {"nodeRef"}) + public List getChildAssocs(NodeRef nodeRef) throws InvalidNodeRefException; + + /** + * Gets all child associations where the pattern of the association qualified + * name is a match. Using a {@link org.alfresco.service.namespace.RegexQNamePattern#MATCH_ALL wildcard} + * for the type and a specific {@link QName qualified name} for the association is + * akin to using the XPath browse expression ./{url}localname in the context of the + * parent node. + *

    + * Note that all child associations are fetched and preloading is done for all results. + * + * @param nodeRef the parent node - usually a container + * @param typeQNamePattern the pattern that the type qualified name of the association must match + * @param qnamePattern the pattern that the qnames of the assocs must match + * @return Returns a list of ChildAssociationRef instances. If the + * node is not a container then the result will be empty. + * @throws InvalidNodeRefException if the node could not be found + * + * @see QName + * @see org.alfresco.service.namespace.RegexQNamePattern#MATCH_ALL + * @see #getChildAssocs(NodeRef, QNamePattern, QNamePattern, int, boolean) + */ + @Auditable(parameters = {"nodeRef", "typeQNamePattern", "qnamePattern"}) + public List getChildAssocs( + NodeRef nodeRef, + QNamePattern typeQNamePattern, + QNamePattern qnamePattern) + throws InvalidNodeRefException; + + /** + * Gets all child associations where the pattern of the association qualified + * name is an exact match. + * + * @param nodeRef the parent node - usually a container + * @param typeQNamePattern the qualified name of the association (null to ignore) + * @param qnamePattern the path qualified name (null to ignore) + * @param maxResults the number of results to get + * @param preload true if the nodes must be preloaded into the cache + * @return Returns a list of ChildAssociationRef instances + * @throws InvalidNodeRefException if the node could not be found + * + * @see QName + */ + @Auditable(parameters = {"nodeRef", "typeQNamePattern", "qnamePattern", "maxResults", "preload"}) + public List getChildAssocs( + NodeRef nodeRef, + final QNamePattern typeQNamePattern, + final QNamePattern qnamePattern, + final int maxResults, + final boolean preload) + throws InvalidNodeRefException; + + /** + * Gets all child associations where the pattern of the association qualified + * names match the patterns provided. + *

    + * Note that all results are retrieved but preloading is optional. + * + * @param nodeRef the parent node - usually a container + * @param typeQNamePattern the qualified name pattern of the association + * @param qnamePattern the path qualified name pattern + * @param preload true if the nodes must be preloaded into the cache + * @return Returns a list of ChildAssociationRef instances + * @throws InvalidNodeRefException if the node could not be found + * + * @see RegexQNamePattern#MATCH_ALL + * @see QName + * @see #getChildAssocs(NodeRef, QNamePattern, QNamePattern, int, boolean) + */ + @Auditable(parameters = {"nodeRef", "typeQNamePattern", "qnamePattern"}) + public List getChildAssocs( + NodeRef nodeRef, + QNamePattern typeQNamePattern, + QNamePattern qnamePattern, + boolean preload) + throws InvalidNodeRefException; + + /** + * Retrieve immediate children of a given node where the child nodes are in the given inclusive list. + * @param nodeRef the parent node - usually a container + * @param childNodeTypeQNames the types that the children may be. Subtypes are not automatically calculated + * and the list must therefore be exhaustive. + * @return Returns a list of ChildAssociationRef instances. + * @throws InvalidNodeRefException if the node could not be found + */ + @Auditable(parameters = {"nodeRef", "childNodeTypes"}) + public List getChildAssocs(NodeRef nodeRef, Set childNodeTypeQNames); + + /** + * Retrieve the immediate children of a given node based on the value of a property of those + * children. + *

    + * If the property to be searched is multi-valued then will match on any one values. + *

    + * Please note, the following system maintained properties that cannot be used with this method. + *

      + *
    • cm:name - use getChildByName instead
    • + *
    • cm:created
    • + *
    • cm:creator
    • + *
    • cm:modified
    • + *
    • cm:modifier
    • + *
    • sys:node-uuid
    • + *
    • sys:node-dbid
    • + *
    • sys:store-identifier
    • + *
    • sys:store-protocol
    • + *
    + * + * @param nodeRef the parent node - usually a container + * @param propertyQName the fully qualified name of the property + * @param value the value to search for. Must be a simple type such as + * String, Number, Date or Boolean, it cannot be a collection, + * a content property, MLText or a float. + * @return Returns a list of ChildAssociationRef instances. + */ + @Auditable(parameters = {"nodeRef", "propertyQName", "value"}) + public List getChildAssocsByPropertyValue( + NodeRef nodeRef, + QName propertyQName, + Serializable value); + + /** + * Get the node with the given name within the context of the parent node. The name + * is case-insensitive as Alfresco has to support case-insensitive clients as standard. + *

    + * That API method getChildByName only works for associations that don't allow duplicate child names. + * See cm:folder and the duplicate tag. Child associations without this allow duplicate + * child names and therefore it is possible to have multiple children with the same name stored against + * the given association type. + * + * @param nodeRef the parent node - usuall a container + * @param assocTypeQName the type of the association + * @param childName the name of the node as per the property cm:name + * @return Returns the child node or null if not found + */ + @Auditable(parameters = {"nodeRef", "assocTypeQName", "childName"}) + public NodeRef getChildByName( + NodeRef nodeRef, + QName assocTypeQName, + String childName); + + /** + * Get the nodes with the given names within the context of the parent node. + * + * @param childNames a collection of up to 1000 child names to match on + * + * @see #getChildByName(NodeRef, QName, String) + */ + @Auditable(parameters = {"nodeRef", "assocTypeQName", "childName"}) + public List getChildrenByName( + NodeRef nodeRef, + QName assocTypeQName, + Collection childNames); + + /** + * Fetches the primary parent-child relationship. + *

    + * For a root node, the parent node reference will be null. + * + * @param nodeRef NodeRef + * @return Returns the primary parent-child association of the node + * @throws InvalidNodeRefException if the node could not be found + */ + @Auditable(parameters = {"nodeRef"}) + public ChildAssociationRef getPrimaryParent(NodeRef nodeRef) throws InvalidNodeRefException; + + /** + * Gets the set of child associations of a certain parent node without parent associations of a certain type to + * other nodes with the same parent! In effect the 'orphans' with respect to a certain association type. + * + * @param parent + * the parent node reference + * @param assocTypeQName + * the association type QName + * @return a set of child associations + */ + @Auditable(parameters = {"parent", "assocTypeQName"}) + public Collection getChildAssocsWithoutParentAssocsOfType( + final NodeRef parent, + final QName assocTypeQName); + + /** + * Create a peer association between two nodes. + *

    + * The ordering will be natural. + * To change association ordering, use {@link #setAssociations(NodeRef, QName, List) setAssociations}. + * + * @param sourceRef a reference to a real node + * @param targetRef a reference to a node + * @param assocTypeQName the qualified name of the association type + * @return Returns a reference to the new association + * @throws InvalidNodeRefException if either of the nodes could not be found + * @throws AssociationExistsException if an association of the same type exists between the nodes + * + * @see #setAssociations(NodeRef, QName, List) + */ + @Auditable(parameters = {"sourceRef", "targetRef", "assocTypeQName"}) + public AssociationRef createAssociation(NodeRef sourceRef, NodeRef targetRef, QName assocTypeQName) + throws InvalidNodeRefException, AssociationExistsException; + + /** + * + * @param sourceRef the associaton source node + * @param targetRef the association target node + * @param assocTypeQName the qualified name of the association type + * @throws InvalidNodeRefException if either of the nodes could not be found + */ + @Auditable(parameters = {"sourceRef", "targetRef", "assocTypeQName"}) + public void removeAssociation(NodeRef sourceRef, NodeRef targetRef, QName assocTypeQName) + throws InvalidNodeRefException; + + /** + * Re-assign all typed target associations for a given node. + * + * @param sourceRef the source node + * @param assocTypeQName the specific type of the association + * @param targetRefs the target nodes (not null but empty list is accepted). + */ + @Auditable(parameters = {"sourceRef", "assocTypeQName", "targetRefs"}) + public void setAssociations(NodeRef sourceRef, QName assocTypeQName, List targetRefs); + + /** + * Gets an association by ID. + * + * @param id + * the association id + * @return the association, or null if it does not exist + */ + public AssociationRef getAssoc(Long id); + + /** + * Fetches all associations from the given source where the associations' + * qualified names match the pattern provided. + *

    + * The results are ordered if a specific type of association is requested + * + * @param sourceRef the association source + * @param qnamePattern the association qname pattern to match against + * @return a list of NodeAssocRef instances for which the + * given node is a source + * @throws InvalidNodeRefException if the source node could not be found + * + * @see QName + * @see org.alfresco.service.namespace.RegexQNamePattern#MATCH_ALL + */ + @Auditable(parameters = {"sourceRef", "qnamePattern"}) + public List getTargetAssocs(NodeRef sourceRef, QNamePattern qnamePattern) + throws InvalidNodeRefException; + + /** + * Fetches all associations from the given source where the associations' + * qualified names match the pattern provided. + *

    + * The results are ordered if a specific type of association is requested + * + * @param sourceRef the association source + * @param qnamePattern the association qname pattern to match against + * @param propertyQName the fully qualified name of the property of the association target. Optional parameter - can be null. + * @param propertyValue association target property value to search for. Must be a simple type such as + * String, Number, Date or Boolean, it cannot be a collection, + * a content property, MLText or a float. If propertyQName is null the value is ignored. + * @return a list of AssociationRef instances for which the + * given node is a source + * @throws InvalidNodeRefException if the source node could not be + * @throws IllegalArgumentException if propertyQName is a system maintained property + * + * @see QName + * @see org.alfresco.service.namespace.RegexQNamePattern#MATCH_ALL + */ + @Auditable(parameters = {"sourceRef", "qnamePattern", "propertyQName", "propertyValue"}) + public List getTargetAssocsByPropertyValue(NodeRef sourceRef, QNamePattern qnamePattern, QName propertyQName, Serializable propertyValue); + + /** + * Fetches all associations to the given target where the associations' + * qualified names match the pattern provided. + * + * @param targetRef the association target + * @param qnamePattern the association qname pattern to match against + * @return Returns a list of NodeAssocRef instances for which the + * given node is a target + * @throws InvalidNodeRefException + * + * @see QName + * @see org.alfresco.service.namespace.RegexQNamePattern#MATCH_ALL + */ + @Auditable(parameters = {"targetRef", "qnamePattern"}) + public List getSourceAssocs(NodeRef targetRef, QNamePattern qnamePattern) + throws InvalidNodeRefException; + + /** + * The root node has an entry in the path(s) returned. For this reason, there + * will always be at least one path element in the returned path(s). + * The first element will have a null parent reference and qname. + * + * @param nodeRef NodeRef + * @return Returns the path to the node along the primary node path + * @throws InvalidNodeRefException if the node could not be found + * + * @see #getPaths(NodeRef, boolean) + */ + @Auditable(parameters = {"nodeRef"}) + public Path getPath(NodeRef nodeRef) throws InvalidNodeRefException; + + /** + * The root node has an entry in the path(s) returned. For this reason, there + * will always be at least one path element in the returned path(s). + * The first element will have a null parent reference and qname. + * + * @param nodeRef NodeRef + * @param primaryOnly true if only the primary path must be retrieved. If true, the + * result will have exactly one entry. + * @return Returns a List of all possible paths to the given node + * @throws InvalidNodeRefException if the node could not be found + */ + @Auditable(parameters = {"nodeRef", "primaryOnly"}) + public List getPaths(NodeRef nodeRef, boolean primaryOnly) throws InvalidNodeRefException; + + /** + * Get the node where archived items will have gone when deleted from the given store. + * + * @param storeRef the store that items were deleted from + * @return Returns the archive node parent + */ + @Auditable(parameters = {"storeRef"}) + public NodeRef getStoreArchiveNode(StoreRef storeRef); + + /** + * Restore an individual node (along with its sub-tree nodes) to the target location. + * The archived node must have the {@link org.alfresco.model.ContentModel#ASPECT_ARCHIVED archived aspect} + * set against it. This would have been applied when a node was originally {@link #deleteNode(NodeRef) deleted}. + * + * @param archivedNodeRef the archived node + * @param destinationParentNodeRef the parent to move the node into + * or null to use the original + * @param assocTypeQName the primary association type name to use in the new location + * or null to use the original + * @param assocQName the primary association name to use in the new location + * or null to use the original + * @return Returns the reference to the newly created node + */ + @Auditable(parameters = {"archivedNodeRef", "destinationParentNodeRef", "assocTypeQName", "assocQName"}) + public NodeRef restoreNode( + NodeRef archivedNodeRef, + NodeRef destinationParentNodeRef, + QName assocTypeQName, + QName assocQName); + + /** + * General node-find parameters. There may be some combinations of parameters that are not + * valid; look at the specific setter methods to get more information. + * + * @author Derek Hulley + * @since 3.4.0b + */ + public class FindNodeParameters + { + private Long minNodeId; + private Long maxNodeId; + private List nodeTypes; + private List nodeAspects; + private boolean sortAscending; + private int limit; + + /** + * Defaults:
    + * minNodeId: null
    + * maxNodeId: null
    + * nodeTypes: null
    + * nodeAspects: null
    + * sortAscending: true
    + * limit: 10000
    + */ + public FindNodeParameters() + { + limit = 10000; + sortAscending = true; + } + + public Long getMinNodeId() + { + return minNodeId; + } + /** + * The lowest node ID (inclusive) to return + * + * @param minNodeId the minimum node ID or null to ignore + */ + public void setMinNodeId(Long minNodeId) + { + this.minNodeId = minNodeId; + } + public Long getMaxNodeId() + { + return maxNodeId; + } + /** + * The largest node ID (exclusive) to return + * + * @param maxNodeId the maximum node ID or null to ignore + */ + public void setMaxNodeId(Long maxNodeId) + { + this.maxNodeId = maxNodeId; + } + public List getNodeTypes() + { + return nodeTypes; + } + /** + * Set the node types to find. Subtypes will be included automatically. + * + * @param nodeTypes the node types or null to ignore + */ + public void setNodeTypes(List nodeTypes) + { + this.nodeTypes = nodeTypes; + } + public List getNodeAspects() + { + return nodeAspects; + } + /** + * Set the node aspects to find. Subtypes will be included automatically. + * + * @param nodeAspects the node aspects or null to ignore + */ + public void setNodeAspects(List nodeAspects) + { + this.nodeAspects = nodeAspects; + } + public boolean isSortAscending() + { + return sortAscending; + } + /** + * Set the node-ID sort order. + * + * @param sortAscending true to retrieve the nodes in ascending ID order + */ + public void setSortAscending(boolean sortAscending) + { + this.sortAscending = sortAscending; + } + public int getLimit() + { + return limit; + } + /** + * Set the number of results to return. If this too large, then results will be trimmed + * by wrapping classes or might cause excessive resource usage; limit the results and + * requery using the ID-bases limiters. + * + * @param limit the maximum number of results to return + */ + public void setLimit(int limit) + { + this.limit = limit; + } + } + + public List findNodes(FindNodeParameters params); + + /** + * Counts the number of child associations of nodeRef. + * + * @param nodeRef the parent node id + * @param isPrimary count just primary associations? + * + * @return Returns the number of child associations + */ + @Auditable(parameters = {"nodeRef", "isPrimary"}) + public int countChildAssocs(NodeRef nodeRef, boolean isPrimary) throws InvalidNodeRefException; +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/Path.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/Path.java new file mode 100644 index 0000000000..57a7b4a874 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/Path.java @@ -0,0 +1,677 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.io.Serializable; +import java.util.Iterator; +import java.util.LinkedList; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ISO9075; + +/** + * Representation of a simple path e.g. + *

    + *   /x/y/z
    + * 
    + * In the above example, there will be 4 elements, the first being a reference + * to the root node, followed by qname elements for x, y and z. + *

    + * Methods and constructors are available to construct a Path instance + * from a path string or by building the path incrementally, including the ability to + * append and prepend path elements. + *

    + * Path elements supported: + *

      + *
    • /{namespace}name fully qualified element
    • + *
    • /name element using default namespace
    • + *
    • /{namespace}name[n] nth sibling
    • + *
    • /name[n] nth sibling using default namespace
    • + *
    • /descendant-or-self::node() descendent or self
    • + *
    • /. self
    • + *
    • /.. parent
    • + *
    + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public final class Path implements Iterable, Serializable +{ + private static final long serialVersionUID = 3905520514524328247L; + private LinkedList elements; + + public Path() + { + // use linked list so as random access is not required, but both prepending and appending is + elements = new LinkedList(); + } + + /** + * @return Returns a typed iterator over the path elements + */ + public Iterator iterator() + { + return elements.iterator(); + } + + /** + * Add a path element to the beginning of the path. This operation is useful in cases where + * a path is built by traversing up a hierarchy. + * + * @param pathElement Path.Element + * @return Returns this instance of the path + */ + public Path prepend(Path.Element pathElement) + { + elements.addFirst(pathElement); + return this; + } + + /** + * Merge the given path into the beginning of this path. + * + * @param path Path + * @return Returns this instance of the path + */ + public Path prepend(Path path) + { + elements.addAll(0, path.elements); + return this; + } + + /** + * Appends a path element to the end of the path + * + * @param pathElement Path.Element + * @return Returns this instance of the path + */ + public Path append(Path.Element pathElement) + { + elements.addLast(pathElement); + return this; + } + + /** + * Append the given path of this path. + * + * @param path Path + * @return Returns this instance of the path + */ + public Path append(Path path) + { + elements.addAll(path.elements); + return this; + } + + /** + * @return Returns the first element in the path or null if the path is empty + */ + public Element first() + { + return elements.getFirst(); + } + + /** + * @return Returns the last element in the path or null if the path is empty + */ + public Element last() + { + return elements.getLast(); + } + + public int size() + { + return elements.size(); + } + + public Element get(int n) + { + return elements.get(n); + } + + /** + * @return Returns a string path made up of the component elements of this instance + */ + public String toString() + { + StringBuilder sb = new StringBuilder(128); + for (Element element : elements) + { + if((sb.length() > 1) || ((sb.length() == 1) && (sb.charAt(0) != '/'))) + { + sb.append("/"); + } + sb.append(element.getElementString()); + } + return sb.toString(); + } + + /** + * @return Returns a string path made up of the component elements of this instance (prefixed where appropriate) + */ + public String toPrefixString(NamespacePrefixResolver resolver) + { + StringBuilder sb = new StringBuilder(128); + for (Element element : elements) + { + if((sb.length() > 1) || ((sb.length() == 1) && (sb.charAt(0) != '/'))) + { + sb.append("/"); + } + sb.append(element.getPrefixedString(resolver)); + } + return sb.toString(); + } + + /** + * Return the human readable form of the specified node Path. Slow version of the method + * that extracts the name of each node in the Path from the supplied NodeService. + * + * @return human readable form of the Path excluding the final element + */ + public String toDisplayPath(NodeService nodeService, PermissionService permissionService) + { + StringBuilder buf = new StringBuilder(64); + + for (int i=0; i (elements.size() -1)) + { + throw new IndexOutOfBoundsException("Start index " + start + " must be between 0 and " + (elements.size() -1)); + } + if (end < 0 || end > (elements.size() -1)) + { + throw new IndexOutOfBoundsException("End index " + end + " must be between 0 and " + (elements.size() -1)); + } + if (end < start) + { + throw new IndexOutOfBoundsException("End index " + end + " cannot be before start index " + start); + } + Path subPath = new Path(); + for (int i = start; i <= end; i++) + { + subPath.append(this.get(i)); + } + return subPath; + } + + /** + * Override equals to check equality of Path instances + */ + public boolean equals(Object o) + { + if(o == this) + { + return true; + } + if(!(o instanceof Path)) + { + return false; + } + Path other = (Path)o; + return this.elements.equals(other.elements); + } + + /** + * Override hashCode to check hash equality of Path instances + */ + public int hashCode() + { + return elements.hashCode(); + } + + public Path getBaseNamePath(TenantService tenantService) + { + Path basePath = new Path(); + for(Element element : elements) + { + basePath.append(element.getBaseNameElement(tenantService)); + } + return basePath; + } + + /** + * Represents a path element. + *

    + * In /x/y/z, elements are x, y and z. + */ + @AlfrescoPublicApi + public abstract static class Element implements Serializable + { + private static final long serialVersionUID = 5396069341092867660L; + + /** + * @return Returns the path element portion including leading '/' and never null + */ + public abstract String getElementString(); + + /** + * @param tenantService TenantService + * @return Element + */ + @AlfrescoPublicApi + public abstract Element getBaseNameElement(TenantService tenantService); + + /** + * @param resolver namespace prefix resolver + * @return the path element portion (with namespaces converted to prefixes) + */ + public String getPrefixedString(NamespacePrefixResolver resolver) + { + return getElementString(); + } + + /** + * @see #getElementString() + */ + public String toString() + { + return getElementString(); + } + } + + /** + * Represents a qualified path between a parent and a child node, + * including the sibling to retrieve e.g. /{namespace}name[5] + */ + @AlfrescoPublicApi + public static class ChildAssocElement extends Element + { + private static final long serialVersionUID = 3689352104636790840L; + + private ChildAssociationRef ref; + + /** + * @param ref a reference to the specific parent-child association + */ + public ChildAssocElement(ChildAssociationRef ref) + { + this.ref = ref; + } + + @Override + public String getElementString() + { + return createElementString(null); + } + + @Override + public String getPrefixedString(NamespacePrefixResolver resolver) + { + return createElementString(resolver); + } + + public ChildAssociationRef getRef() + { + return ref; + } + + @Override + public boolean equals(Object o) + { + if(o == this) + { + return true; + } + if(!(o instanceof ChildAssocElement)) + { + return false; + } + ChildAssocElement other = (ChildAssocElement)o; + return this.ref.equals(other.ref); + } + + @Override + public int hashCode() + { + return ref.hashCode(); + } + + private String createElementString(NamespacePrefixResolver resolver) + { + StringBuilder sb = new StringBuilder(32); + if (ref.getParentRef() == null) + { + sb.append("/"); + } + else + { + // a parent is present + sb.append(resolver == null ? ISO9075.getXPathName(ref.getQName()) : ISO9075.getXPathName(ref.getQName(), resolver)); + } + if (ref.getNthSibling() > -1) + { + sb.append("[").append(ref.getNthSibling()).append("]"); + } + return sb.toString(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.repository.Path.Element#getBaseNameElement(org.alfresco.repo.tenant.TenantService) + */ + @Override + public Element getBaseNameElement(TenantService tenantService) + { + return new ChildAssocElement(new ChildAssociationRef(ref.getTypeQName(), tenantService.getBaseName(ref.getParentRef(), true), ref.getQName(), tenantService.getBaseName(ref.getChildRef(), true), ref.isPrimary(), ref.getNthSibling())); + } + } + + /** + * Represents a qualified path to an attribute, + * including the sibling for repeated properties/attributes to retrieve e.g. /@{namespace}name[5] + */ + @AlfrescoPublicApi + public static class AttributeElement extends Element + { + private static final long serialVersionUID = 3256727281668863544L; + + private QName attribute; + private int position = -1; + + /** + * @param attribute QName + */ + public AttributeElement(QName attribute) + { + this.attribute = attribute; + } + + public AttributeElement(QName attribute, int position) + { + this(attribute); + this.position = position; + } + + public AttributeElement(String attribute) + { + String qNameStr = null; + int idx = attribute.indexOf("["); + if(idx != -1) + { + String positionStr = attribute.substring(idx + 1, attribute.length() - 1); + position = Integer.parseInt(positionStr); + qNameStr = attribute.substring(1, idx); + } + else + { + qNameStr = attribute.substring(1); + } + this.attribute = ISO9075.parseXPathName(qNameStr); + } + + @Override + public String getElementString() + { + return createElementString(null); + } + + @Override + public String getPrefixedString(NamespacePrefixResolver resolver) + { + return createElementString(resolver); + } + + private String createElementString(NamespacePrefixResolver resolver) + { + StringBuilder sb = new StringBuilder(32); + sb.append("@").append(resolver == null ? ISO9075.getXPathName(attribute) : ISO9075.getXPathName(attribute, resolver)); + + if (position > -1) + { + sb.append("[").append(position).append("]"); + } + return sb.toString(); + } + + public QName getQName() + { + return attribute; + } + + public int position() + { + return position; + } + + public boolean equals(Object o) + { + if(o == this) + { + return true; + } + if(!(o instanceof AttributeElement)) + { + return false; + } + AttributeElement other = (AttributeElement)o; + return this.getQName().equals(other.getQName()) && (this.position() == other.position()); + } + + public int hashCode() + { + return getQName().hashCode()*32 + position(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.repository.Path.Element#getBaseNameElement(org.alfresco.repo.tenant.TenantService) + */ + @Override + public Element getBaseNameElement(TenantService tenantService) + { + return new AttributeElement(attribute, position); + } + + } + + /** + * Represents the // or /descendant-or-self::node() xpath element + */ + @AlfrescoPublicApi + public static class DescendentOrSelfElement extends Element + { + private static final long serialVersionUID = 3258410616875005237L; + + public String getElementString() + { + return "descendant-or-self::node()"; + } + + public boolean equals(Object o) + { + if(o == this) + { + return true; + } + if(!(o instanceof DescendentOrSelfElement)) + { + return false; + } + return true; + } + + public int hashCode() + { + return "descendant-or-self::node()".hashCode(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.repository.Path.Element#getBaseNameElement(org.alfresco.repo.tenant.TenantService) + */ + @Override + public Element getBaseNameElement(TenantService tenantService) + { + return new DescendentOrSelfElement(); + } + + } + + /** + * Represents the /. xpath element + */ + @AlfrescoPublicApi + public static class SelfElement extends Element + { + private static final long serialVersionUID = 3834311739151300406L; + + public String getElementString() + { + return "."; + } + + public boolean equals(Object o) + { + if(o == this) + { + return true; + } + if(!(o instanceof SelfElement)) + { + return false; + } + return true; + } + + public int hashCode() + { + return ".".hashCode(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.repository.Path.Element#getBaseNameElement(org.alfresco.repo.tenant.TenantService) + */ + @Override + public Element getBaseNameElement(TenantService tenantService) + { + return new SelfElement(); + } + } + + /** + * Represents the /.. xpath element + */ + @AlfrescoPublicApi + public static class ParentElement extends Element + { + private static final long serialVersionUID = 3689915080477456179L; + + public String getElementString() + { + return ".."; + } + + public boolean equals(Object o) + { + if(o == this) + { + return true; + } + if(!(o instanceof ParentElement)) + { + return false; + } + return true; + } + + public int hashCode() + { + return "..".hashCode(); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.repository.Path.Element#getBaseNameElement(org.alfresco.repo.tenant.TenantService) + */ + @Override + public Element getBaseNameElement(TenantService tenantService) + { + return new ParentElement(); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/Period.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/Period.java new file mode 100644 index 0000000000..2600257db3 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/Period.java @@ -0,0 +1,211 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.io.Serializable; +import java.util.Date; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Implementation for the period data type "d:period" A period is specified by the period type and an optional + * expression. The string value is periodType|expression Examples are: none day - one day day|3 - 3 days week - one week + * week|1 - one week week|2 - two weeks month year monthend quarterend The period type specifies a period + * implementation. This is registered with this class and is used to when adding the period to a date, handles any + * processing of the expression, reports if the expression is not required, optional or mandatory. + * The period data type can be also passed as a Map of keys: periodType and expression. + * + * @author andyh + */ +@SuppressWarnings("unchecked") +public class Period implements Serializable +{ + /** + * + */ + private static final long serialVersionUID = -7978001474638355909L; + + // Providers do not serialize + transient private static ConcurrentHashMap providers = new ConcurrentHashMap(); + + /** + * Register a provider + * @param periodProvider PeriodProvider + */ + public static void registerProvider(PeriodProvider periodProvider) + { + providers.put(periodProvider.getPeriodType(), periodProvider); + } + + /** + * Find a provider + * @param periodType String + * @return the provider + * @throws IllegalStateException of there is no implementation + */ + public static PeriodProvider getProvider(String periodType) + { + PeriodProvider provider = providers.get(periodType); + if (provider == null) + { + throw new IllegalStateException("No period provider for period type " + periodType); + } + return provider; + } + + /** + * Get the set of registered providers + * @return - the set of registered providers + */ + public static Set getProviderNames() + { + return providers.keySet(); + } + + private String periodType; + + private String expression; + + /** + * Create a period without an accompanying expression. + * + * @param period String + */ + public Period(String period) + { + String[] parts = period.split("\\|", 2); + periodType = parts[0]; + if (parts.length == 2) + { + expression = parts[1]; + } + } + + /** + * Create a period using key-value + * + * @param source + */ + public Period(Map source) + { + if (source == null) + { + throw new IllegalArgumentException("Cannot create Period."); + } + if (source.get("periodType") == null) + { + throw new IllegalArgumentException("Cannot create Period with null periodType"); + } + + periodType = source.get("periodType"); + expression = source.get("expression"); + } + + /** + * @return the periodType + */ + public String getPeriodType() + { + return periodType; + } + + /** + * @return the expression + */ + public String getExpression() + { + return expression; + } + + /** + * Calculate the next date for this period given the a start date. + * + * @param date Date + * @return the next date. + */ + public Date getNextDate(Date date) + { + if (periodType == null || periodType.length() == 0) + { + return null; + } + + PeriodProvider provider = getProvider(periodType); + return provider.getNextDate(date, expression != null ? expression : provider.getDefaultExpression()); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((expression == null) ? 0 : expression.hashCode()); + result = prime * result + ((periodType == null) ? 0 : periodType.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Period other = (Period) obj; + if (expression == null) + { + if (other.expression != null) + return false; + } + else if (!expression.equals(other.expression)) + return false; + if (periodType == null) + { + if (other.periodType != null) + return false; + } + else if (!periodType.equals(other.periodType)) + return false; + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append(periodType); + if (expression != null) + { + builder.append("|"); + builder.append(expression); + } + return builder.toString(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/PeriodProvider.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/PeriodProvider.java new file mode 100644 index 0000000000..e71b5fd276 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/PeriodProvider.java @@ -0,0 +1,97 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.util.Date; + +import org.alfresco.service.namespace.QName; + +/** + * Provider API for period implementations + * @author andyh + * + */ +public interface PeriodProvider +{ + /** + * Period expression multiplicity + * @author andyh + * + */ + public enum ExpressionMutiplicity + { + /** + * There is no expression + */ + NONE, + /** + * An expression is optional + */ + OPTIONAL, + /** + * An expression is mandatory + */ + MANDATORY + } + + /** + * Get the name for the period. + * @return - period name + */ + public String getPeriodType(); + + /** + * Gets the display label for the period. + * @return display label + */ + public String getDisplayLabel(); + + /** + * Get the next date - the provided date + period + * @param date Date + * @param expression String + * @return the next date in the period + */ + public Date getNextDate(Date date, String expression); + + /** + * Is the expression required etc ... + * @return the multiplicity + */ + public ExpressionMutiplicity getExpressionMutiplicity(); + + /** + * Get the default expression - this could be null + * @return - the default expression. + */ + public String getDefaultExpression(); + + /** + * Return the Alfresco data type QName to which the string value of the expression will be converted. + * @return the alfresco data type or null if an expression is not allowed. + */ + public QName getExpressionDataType(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/StoreExistsException.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/StoreExistsException.java new file mode 100644 index 0000000000..522b16f999 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/StoreExistsException.java @@ -0,0 +1,45 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Thrown when an operation cannot be performed because the store reference + * no longer exists. + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public class StoreExistsException extends AbstractStoreException +{ + private static final long serialVersionUID = 3906369320370975030L; + + public StoreExistsException(StoreRef storeRef, Throwable e) + { + super(storeRef, e); + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/StoreRef.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/StoreRef.java new file mode 100644 index 0000000000..c6a4d8898c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/StoreRef.java @@ -0,0 +1,129 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.io.Serializable; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.error.AlfrescoRuntimeException; + +/** + * Reference to a node store + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public final class StoreRef implements EntityRef, Serializable +{ + private static final long serialVersionUID = 3905808565129394486L; + + public static final String PROTOCOL_WORKSPACE = "workspace"; + public static final String PROTOCOL_ARCHIVE = "archive"; + public static final String PROTOCOL_AVM = "avm"; + public static final String PROTOCOL_TEST = "test"; + public static final String PROTOCOL_DELETED = "deleted"; + + public static final StoreRef STORE_REF_WORKSPACE_SPACESSTORE = new StoreRef(PROTOCOL_WORKSPACE, "SpacesStore"); + public static final StoreRef STORE_REF_ARCHIVE_SPACESSTORE = new StoreRef(PROTOCOL_ARCHIVE, "SpacesStore"); + + public static final String URI_FILLER = "://"; + + private final String protocol; + private final String identifier; + + /** + * @param protocol + * well-known protocol for the store, e.g. workspace or + * versionstore + * @param identifier + * the identifier, which may be specific to the protocol + */ + public StoreRef(String protocol, String identifier) + { + if (protocol == null) + { + throw new IllegalArgumentException("Store protocol may not be null"); + } + if (identifier == null) + { + throw new IllegalArgumentException("Store identifier may not be null"); + } + + this.protocol = protocol; + this.identifier = identifier; + } + + public StoreRef(String string) + { + int dividerPatternPosition = string.indexOf(URI_FILLER); + if(dividerPatternPosition == -1) + { + throw new AlfrescoRuntimeException("Invalid store ref: Does not contain " + URI_FILLER + " " + string); + } + this.protocol = string.substring(0, dividerPatternPosition); + this.identifier = string.substring(dividerPatternPosition+3); + } + + public String toString() + { + return protocol + URI_FILLER + identifier; + } + + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj instanceof StoreRef) + { + StoreRef that = (StoreRef) obj; + return (this.protocol.equals(that.protocol) + && this.identifier.equals(that.identifier)); + } else + { + return false; + } + } + + /** + * Creates a hashcode from both the {@link #getProtocol()} and {@link #getIdentifier()} + */ + public int hashCode() + { + return (protocol.hashCode() + identifier.hashCode()); + } + + public String getProtocol() + { + return protocol; + } + + public String getIdentifier() + { + return identifier; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/XPathException.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/XPathException.java new file mode 100644 index 0000000000..87d4d5aa34 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/XPathException.java @@ -0,0 +1,43 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import org.alfresco.error.AlfrescoRuntimeException; + +public class XPathException extends AlfrescoRuntimeException +{ + private static final long serialVersionUID = 3544955454552815923L; + + public XPathException(String msg) + { + super(msg); + } + + public XPathException(String msg, Throwable cause) + { + super(msg, cause); + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverter.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverter.java new file mode 100644 index 0000000000..bff00b7547 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverter.java @@ -0,0 +1,873 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository.datatype; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Timestamp; +import java.text.DecimalFormat; +import java.text.ParseException; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.Map; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.opencmis.search.CMISQueryOptions; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.EntityRef; +import org.alfresco.service.cmr.repository.MLText; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.cmr.repository.Period; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.SearchParameters; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ISO8601DateFormat; +import org.alfresco.util.VersionNumber; +import org.springframework.extensions.surf.exception.PlatformRuntimeException; +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * Support for generic conversion between types. + * + * Additional conversions may be added. Basic inter-operability supported. + * + * Direct conversion and two stage conversions via Number are supported. We do + * not support conversion by any route at the moment + * + * TODO: Add support for Path + * + * TODO: Add support for lucene + * + * TODO: Add suport to check of a type is convertable + * + * TODO: Support for dynamically managing conversions + * + * @author andyh + * + */ +@AlfrescoPublicApi +public class DefaultTypeConverter extends TypeConverter +{ + /** + * Default Type Converter + */ + public static TypeConverter INSTANCE = new DefaultTypeConverter(); + + @SuppressWarnings("rawtypes") + private DefaultTypeConverter() + { + // + // From string + // + addConverter(String.class, Class.class, new TypeConverter.Converter() + { + public Class convert(String source) + { + try + { + return Class.forName(source); + } + catch (ClassNotFoundException e) + { + throw new TypeConversionException("Failed to convert string to class: " + source, e); + } + } + }); + addConverter(String.class, Boolean.class, new TypeConverter.Converter() + { + public Boolean convert(String source) + { + return Boolean.valueOf(source); + } + }); + addConverter(String.class, Character.class, new TypeConverter.Converter() + { + public Character convert(String source) + { + if ((source == null) || (source.length() == 0)) + { + return null; + } + return Character.valueOf(source.charAt(0)); + } + }); + addConverter(String.class, Number.class, new TypeConverter.Converter() + { + public Number convert(String source) + { + try + { + return DecimalFormat.getNumberInstance().parse(source); + } + catch (ParseException e) + { + throw new TypeConversionException("Failed to parse number " + source, e); + } + } + }); + addConverter(String.class, Byte.class, new TypeConverter.Converter() + { + public Byte convert(String source) + { + return Byte.valueOf(source); + } + }); + addConverter(String.class, Short.class, new TypeConverter.Converter() + { + public Short convert(String source) + { + return Short.valueOf(source); + } + }); + addConverter(String.class, Integer.class, new TypeConverter.Converter() + { + public Integer convert(String source) + { + return Integer.valueOf(source); + } + }); + addConverter(String.class, Long.class, new TypeConverter.Converter() + { + public Long convert(String source) + { + return Long.valueOf(source); + } + }); + addConverter(String.class, Float.class, new TypeConverter.Converter() + { + public Float convert(String source) + { + return Float.valueOf(source); + } + }); + addConverter(String.class, Double.class, new TypeConverter.Converter() + { + public Double convert(String source) + { + return Double.valueOf(source); + } + }); + addConverter(String.class, BigInteger.class, new TypeConverter.Converter() + { + public BigInteger convert(String source) + { + return new BigInteger(source); + } + }); + addConverter(String.class, BigDecimal.class, new TypeConverter.Converter() + { + public BigDecimal convert(String source) + { + return new BigDecimal(source); + } + }); + addConverter(String.class, Date.class, new TypeConverter.Converter() + { + public Date convert(String source) + { + try + { + Date date = ISO8601DateFormat.parse(source); + return date; + } + catch (PlatformRuntimeException e) + { + throw new TypeConversionException("Failed to convert date " + source + " to string", e); + } + catch (AlfrescoRuntimeException e) + { + throw new TypeConversionException("Failed to convert date " + source + " to string", e); + } + } + }); + addConverter(String.class, Duration.class, new TypeConverter.Converter() + { + public Duration convert(String source) + { + return new Duration(source); + } + }); + addConverter(String.class, QName.class, new TypeConverter.Converter() + { + public QName convert(String source) + { + return QName.createQName(source); + } + }); + addConverter(String.class, ContentData.class, new TypeConverter.Converter() + { + public ContentData convert(String source) + { + return ContentData.createContentProperty(source); + } + }); + addConverter(String.class, NodeRef.class, new TypeConverter.Converter() + { + public NodeRef convert(String source) + { + return new NodeRef(source); + } + }); + addConverter(String.class, StoreRef.class, new TypeConverter.Converter() + { + public StoreRef convert(String source) + { + return new StoreRef(source); + } + }); + addConverter(String.class, ChildAssociationRef.class, new TypeConverter.Converter() + { + public ChildAssociationRef convert(String source) + { + return new ChildAssociationRef(source); + } + }); + addConverter(String.class, AssociationRef.class, new TypeConverter.Converter() + { + public AssociationRef convert(String source) + { + return new AssociationRef(source); + } + }); + addConverter(String.class, InputStream.class, new TypeConverter.Converter() + { + public InputStream convert(String source) + { + try + { + return new ByteArrayInputStream(source.getBytes("UTF-8")); + } + catch (UnsupportedEncodingException e) + { + throw new TypeConversionException("Encoding not supported", e); + } + } + }); + addConverter(String.class, MLText.class, new TypeConverter.Converter() + { + public MLText convert(String source) + { + return new MLText(source); + } + }); + addConverter(String.class, Locale.class, new TypeConverter.Converter() + { + public Locale convert(String source) + { + return I18NUtil.parseLocale(source); + } + }); + addConverter(String.class, Period.class, new TypeConverter.Converter() + { + public Period convert(String source) + { + return new Period(source); + } + }); + addConverter(Map.class, Period.class, new TypeConverter.Converter() + { + public Period convert(Map source) + { + return new Period(source); + } + }); + addConverter(String.class, VersionNumber.class, new TypeConverter.Converter() + { + public VersionNumber convert(String source) + { + return new VersionNumber(source); + } + }); + + // + // From Locale + // + addConverter(Locale.class, String.class, new TypeConverter.Converter() + { + public String convert(Locale source) + { + String localeStr = source.toString(); + if (localeStr.length() < 6) + { + localeStr += "_"; + } + return localeStr; + } + }); + + + // + // From VersionNumber + // + addConverter(VersionNumber.class, String.class, new TypeConverter.Converter() + { + public String convert(VersionNumber source) + { + return source.toString(); + } + }); + + + // + // From MLText + // + addConverter(MLText.class, String.class, new TypeConverter.Converter() + { + public String convert(MLText source) + { + return source.getDefaultValue(); + } + }); + + // + // From enum + // + addConverter(Enum.class, String.class, new TypeConverter.Converter() + { + public String convert(Enum source) + { + return source.toString(); + } + }); + + // From Period + addConverter(Period.class, String.class, new TypeConverter.Converter() + { + public String convert(Period source) + { + return source.toString(); + } + }); + + // From Class + addConverter(Class.class, String.class, new TypeConverter.Converter() + { + public String convert(Class source) + { + return source.getName(); + } + }); + + // + // Number to Subtypes and Date + // + addConverter(Number.class, Boolean.class, new TypeConverter.Converter() + { + public Boolean convert(Number source) + { + return new Boolean(source.longValue() > 0); + } + }); + addConverter(Number.class, Byte.class, new TypeConverter.Converter() + { + public Byte convert(Number source) + { + return Byte.valueOf(source.byteValue()); + } + }); + addConverter(Number.class, Short.class, new TypeConverter.Converter() + { + public Short convert(Number source) + { + return Short.valueOf(source.shortValue()); + } + }); + addConverter(Number.class, Integer.class, new TypeConverter.Converter() + { + public Integer convert(Number source) + { + return Integer.valueOf(source.intValue()); + } + }); + addConverter(Number.class, Long.class, new TypeConverter.Converter() + { + public Long convert(Number source) + { + return Long.valueOf(source.longValue()); + } + }); + addConverter(Number.class, Float.class, new TypeConverter.Converter() + { + public Float convert(Number source) + { + return Float.valueOf(source.floatValue()); + } + }); + addConverter(Number.class, Double.class, new TypeConverter.Converter() + { + public Double convert(Number source) + { + return Double.valueOf(source.doubleValue()); + } + }); + addConverter(Number.class, Date.class, new TypeConverter.Converter() + { + public Date convert(Number source) + { + return new Date(source.longValue()); + } + }); + addConverter(Number.class, String.class, new TypeConverter.Converter() + { + public String convert(Number source) + { + return source.toString(); + } + }); + addConverter(Number.class, BigInteger.class, new TypeConverter.Converter() + { + public BigInteger convert(Number source) + { + if (source instanceof BigDecimal) + { + return ((BigDecimal) source).toBigInteger(); + } + else + { + return BigInteger.valueOf(source.longValue()); + } + } + }); + addConverter(Number.class, BigDecimal.class, new TypeConverter.Converter() + { + public BigDecimal convert(Number source) + { + if (source instanceof BigInteger) + { + return new BigDecimal((BigInteger) source); + } + else if(source instanceof Double) + { + return BigDecimal.valueOf((Double) source); + } + else if(source instanceof Float) + { + Float val = (Float)source; + if(val.isInfinite()) + { + // What else can we do here? this is 3.4 E 38 so is fairly big + return new BigDecimal(Float.MAX_VALUE); + } + return BigDecimal.valueOf((Float) source); + } + else + { + return BigDecimal.valueOf(source.longValue()); + } + } + }); + addDynamicTwoStageConverter(Number.class, String.class, InputStream.class); + + // + // Date, Timestamp -> + // + addConverter(Timestamp.class, Date.class, new TypeConverter.Converter() + { + public Date convert(Timestamp source) + { + return new Date(source.getTime()); + } + }); + addConverter(Date.class, Number.class, new TypeConverter.Converter() + { + public Number convert(Date source) + { + return Long.valueOf(source.getTime()); + } + }); + addConverter(Date.class, String.class, new TypeConverter.Converter() + { + public String convert(Date source) + { + try + { + return ISO8601DateFormat.format(source); + } + catch (PlatformRuntimeException e) + { + throw new TypeConversionException("Failed to convert date " + source + " to string", e); + } + } + }); + addConverter(Date.class, Calendar.class, new TypeConverter.Converter() + { + public Calendar convert(Date source) + { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(source); + return calendar; + } + }); + + addConverter(Date.class, GregorianCalendar.class, new TypeConverter.Converter() + { + public GregorianCalendar convert(Date source) + { + GregorianCalendar calendar = new GregorianCalendar(); + calendar.setTime(source); + return calendar; + } + }); + addDynamicTwoStageConverter(Date.class, String.class, InputStream.class); + + // + // Boolean -> + // + final Long LONG_FALSE = new Long(0L); + final Long LONG_TRUE = new Long(1L); + addConverter(Boolean.class, Long.class, new TypeConverter.Converter() + { + public Long convert(Boolean source) + { + return source.booleanValue() ? LONG_TRUE : LONG_FALSE; + } + }); + addConverter(Boolean.class, String.class, new TypeConverter.Converter() + { + public String convert(Boolean source) + { + return source.toString(); + } + }); + addDynamicTwoStageConverter(Boolean.class, String.class, InputStream.class); + + // + // Character -> + // + addConverter(Character.class, String.class, new TypeConverter.Converter() + { + public String convert(Character source) + { + return source.toString(); + } + }); + addDynamicTwoStageConverter(Character.class, String.class, InputStream.class); + + // + // Duration -> + // + addConverter(Duration.class, String.class, new TypeConverter.Converter() + { + public String convert(Duration source) + { + return source.toString(); + } + + }); + addDynamicTwoStageConverter(Duration.class, String.class, InputStream.class); + + // + // Byte + // + addConverter(Byte.class, String.class, new TypeConverter.Converter() + { + public String convert(Byte source) + { + return source.toString(); + } + }); + addDynamicTwoStageConverter(Byte.class, String.class, InputStream.class); + + // + // Short + // + addConverter(Short.class, String.class, new TypeConverter.Converter() + { + public String convert(Short source) + { + return source.toString(); + } + }); + addDynamicTwoStageConverter(Short.class, String.class, InputStream.class); + + // + // Integer + // + addConverter(Integer.class, String.class, new TypeConverter.Converter() + { + public String convert(Integer source) + { + return source.toString(); + } + }); + addDynamicTwoStageConverter(Integer.class, String.class, InputStream.class); + + // + // Long + // + addConverter(Long.class, String.class, new TypeConverter.Converter() + { + public String convert(Long source) + { + return source.toString(); + } + }); + addDynamicTwoStageConverter(Long.class, String.class, InputStream.class); + + // + // Float + // + addConverter(Float.class, String.class, new TypeConverter.Converter() + { + public String convert(Float source) + { + return source.toString(); + } + }); + addDynamicTwoStageConverter(Float.class, String.class, InputStream.class); + + // + // Double + // + addConverter(Double.class, String.class, new TypeConverter.Converter() + { + public String convert(Double source) + { + return source.toString(); + } + }); + addDynamicTwoStageConverter(Double.class, String.class, InputStream.class); + + // + // BigInteger + // + addConverter(BigInteger.class, String.class, new TypeConverter.Converter() + { + public String convert(BigInteger source) + { + return source.toString(); + } + }); + addDynamicTwoStageConverter(BigInteger.class, String.class, InputStream.class); + + // + // Calendar + // + addConverter(Calendar.class, Date.class, new TypeConverter.Converter() + { + public Date convert(Calendar source) + { + return source.getTime(); + } + }); + addConverter(Calendar.class, String.class, new TypeConverter.Converter() + { + public String convert(Calendar source) + { + try + { + return ISO8601DateFormat.format(source.getTime()); + } + catch (PlatformRuntimeException e) + { + throw new TypeConversionException("Failed to convert date " + source + " to string", e); + } + } + }); + + // + // BigDecimal + // + addConverter(BigDecimal.class, String.class, new TypeConverter.Converter() + { + public String convert(BigDecimal source) + { + return source.toString(); + } + }); + addDynamicTwoStageConverter(BigDecimal.class, String.class, InputStream.class); + + // + // QName + // + addConverter(QName.class, String.class, new TypeConverter.Converter() + { + public String convert(QName source) + { + return source.toString(); + } + }); + addDynamicTwoStageConverter(QName.class, String.class, InputStream.class); + + // + // EntityRef (NodeRef, ChildAssociationRef, NodeAssociationRef) + // + addConverter(EntityRef.class, String.class, new TypeConverter.Converter() + { + public String convert(EntityRef source) + { + return source.toString(); + } + }); + addDynamicTwoStageConverter(EntityRef.class, String.class, InputStream.class); + + // + // ContentData + // + addConverter(ContentData.class, String.class, new TypeConverter.Converter() + { + public String convert(ContentData source) + { + return source.getInfoUrl(); + } + }); + addDynamicTwoStageConverter(ContentData.class, String.class, InputStream.class); + + // + // Path + // + addConverter(Path.class, String.class, new TypeConverter.Converter() + { + public String convert(Path source) + { + return source.toString(); + } + }); + addDynamicTwoStageConverter(Path.class, String.class, InputStream.class); + + // + // ContentReader + // + addConverter(ContentReader.class, InputStream.class, new TypeConverter.Converter() + { + public InputStream convert(ContentReader source) + { + return source.getContentInputStream(); + } + }); + addConverter(ContentReader.class, String.class, new TypeConverter.Converter() + { + public String convert(ContentReader source) + { + // Getting the string from the ContentReader binary is meaningless + return source.toString(); + } + }); + + // + // ContentWriter + // + addConverter(ContentWriter.class, String.class, new TypeConverter.Converter() + { + public String convert(ContentWriter source) + { + return source.toString(); + } + }); + + // + // InputStream + // + addConverter(InputStream.class, String.class, new TypeConverter.Converter() + { + public String convert(InputStream source) + { + try + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buffer = new byte[8192]; + int read; + while ((read = source.read(buffer)) > 0) + { + out.write(buffer, 0, read); + } + byte[] data = out.toByteArray(); + return new String(data, "UTF-8"); + } + catch (UnsupportedEncodingException e) + { + throw new TypeConversionException("Cannot convert input stream to String.", e); + } + catch (IOException e) + { + throw new TypeConversionException("Conversion from stream to string failed", e); + } + finally + { + if (source != null) + { + try + { + source.close(); + } + catch(IOException e) + { + //NOOP + } + } + } + } + }); + + addDynamicTwoStageConverter(InputStream.class, String.class, Date.class); + + addDynamicTwoStageConverter(InputStream.class, String.class, Double.class); + + addDynamicTwoStageConverter(InputStream.class, String.class, Long.class); + + addDynamicTwoStageConverter(InputStream.class, String.class, Boolean.class); + + addDynamicTwoStageConverter(InputStream.class, String.class, QName.class); + + addDynamicTwoStageConverter(InputStream.class, String.class, Path.class); + + addDynamicTwoStageConverter(InputStream.class, String.class, NodeRef.class); + + + // + // SearchParameters & CMISQuery (for audit) + // + + addConverter(SearchParameters.class, String.class, new TypeConverter.Converter() + { + public String convert(SearchParameters source) + { + return source.toAuditString(); + } + }); + addConverter(CMISQueryOptions.class, String.class, new TypeConverter.Converter() + { + public String convert(CMISQueryOptions source) + { + return source.getAsSearchParmeters().toAuditString(); + } + }); + } + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/datatype/Duration.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/datatype/Duration.java new file mode 100644 index 0000000000..40637a6177 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/datatype/Duration.java @@ -0,0 +1,1094 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository.datatype; + +import java.io.IOException; +import java.io.Serializable; +import java.io.StreamTokenizer; +import java.io.StringReader; +import java.math.BigDecimal; +import java.text.DateFormat; +import java.text.NumberFormat; +import java.text.ParsePosition; +import java.util.Calendar; +import java.util.Date; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.util.CachingDateFormat; + +/** + * This data type represents duration/interval/period as defined by the XMLSchema type + * duration. + * + * The lexical representation of duration is + * PnYnMnDTnHnMnS. + * + * P is a literal value that starts the expression + * nY is an integer number of years followed by the literal Y + * nM is an integer number of months followed by the literal M + * nD is an integer number of days followed by the literal D + * T is the literal that separates the date and time + * nH is an integer number of hours followed by a literal H + * nM is an integer number of minutes followed by a literal M + * nS is a decimal number of seconds followed by a literal S + * + * Any numbers and designator may be absent if the value is zero. + * A minus sign may appear before the literal P to indicate a negative duration. + * If no time items are present the literal T must not appear. + * + * + * This implementation is immutable and thread safe. + * + * There are two forms of duration common on database types. + * The code contains warnings wheer these are relevant. + * + * @author andyh + */ +@AlfrescoPublicApi +public class Duration implements Comparable, Serializable +{ + + static final long serialVersionUID = 3274526442325176068L; + + public static final String XML_DAY = "P1D"; + public static final String XML_WEEK = "P7D"; + public static final String XML_TWO_WEEKS = "P14D"; + public static final String XML_MONTH = "P1M"; + public static final String XML_QUARTER = "P3M"; + public static final String XML_SIX_MONTHS = "P6M"; + public static final String XML_YEAR = "P1Y"; + + public static final Duration DAY = new Duration(XML_DAY); + public static final Duration WEEK = new Duration(XML_WEEK); + public static final Duration TWO_WEEKS = new Duration(XML_TWO_WEEKS); + public static final Duration MONTH = new Duration(XML_MONTH); + public static final Duration QUARTER = new Duration(XML_QUARTER); + public static final Duration SIX_MONTHS = new Duration(XML_SIX_MONTHS); + public static final Duration YEAR = new Duration(XML_YEAR); + + private static final String s_parse = "-PYMDTHmS"; + + private boolean m_positive = true; + private int m_years = 0; + private int m_months = 0; + private int m_days = 0; + private int m_hours = 0; + private int m_mins = 0; + private int m_seconds = 0; + private int m_nanos = 0; + + // Date duration arithmetic + + /** + * Add a duration to a date and return the date plus the specified increment. + * + * @param date - the initial date + * @param duration - the duration to add on to the date (the duration may be negative) + * @return the adjusted date. + */ + public static Date add(Date date, Duration duration) + { + Calendar c = Calendar.getInstance(); + c.setTime(date); + c.add(Calendar.YEAR, (duration.m_positive ? 1 : -1) * duration.m_years); + c.add(Calendar.MONTH, (duration.m_positive ? 1 : -1) * duration.m_months); + c.add(Calendar.DATE, (duration.m_positive ? 1 : -1) * duration.m_days); + c.add(Calendar.HOUR_OF_DAY, (duration.m_positive ? 1 : -1) * duration.m_hours); + c.add(Calendar.MINUTE, (duration.m_positive ? 1 : -1) * duration.m_mins); + c.add(Calendar.SECOND, (duration.m_positive ? 1 : -1) * duration.m_seconds); + c.add(Calendar.MILLISECOND, (duration.m_positive ? 1 : -1) * duration.m_nanos / 1000000); + return c.getTime(); + } + + /** + * Subtract a period for a given date + * + * @param date - the intial date + * @param duration - the diration to subtract + * @return the adjusted date. + */ + + public static Date subtract(Date date, Duration duration) + { + return add(date, duration.unaryMinus()); + } + + + + /** + * Constructor for Duration - a zero value duration + */ + + public Duration() + { + super(); + } + + /** + * Construct a Duration from the XMLSchema definition + */ + + public Duration(String duration) + { + + if (duration.equals("P")) + { + throw new RuntimeException("Invalid period: P"); + } + + if (!duration.startsWith("P") && !duration.startsWith("-P")) + { + throw new RuntimeException("Invalid period: must start with P or -P"); + } + else + { + boolean dateMode = true; + int last = -1; + Double nval = null; + StringReader reader = new StringReader(duration); + StreamTokenizer tok = new StreamTokenizer(reader); + tok.resetSyntax(); + tok.eolIsSignificant(true); + tok.parseNumbers(); + tok.ordinaryChars('-', '-'); + tok.ordinaryChars('P', 'P'); + tok.ordinaryChars('Y', 'Y'); + tok.ordinaryChars('M', 'M'); + tok.ordinaryChars('D', 'D'); + tok.ordinaryChars('T', 'T'); + tok.ordinaryChars('H', 'H'); + tok.ordinaryChars('m', 'm'); + tok.ordinaryChars('S', 'S'); + + int token; + try + { + while ((token = tok.nextToken()) != StreamTokenizer.TT_EOF) + { + if (token == StreamTokenizer.TT_NUMBER) + { + nval = new Double(tok.nval); + } + else if (token == StreamTokenizer.TT_EOF) + { + throw new RuntimeException("Invalid EOF in Duration"); + } + else if (token == StreamTokenizer.TT_EOL) + { + throw new RuntimeException("Invalid EOL in Duration"); + } + else if (token == StreamTokenizer.TT_WORD) + { + throw new RuntimeException("Invalid text in Duration: " + tok.sval); + } + else + { + if (tok.ttype == '-') + { + last = checkIndex(last, "-"); + m_positive = false; + } + else if (tok.ttype == 'P') + { + last = checkIndex(last, "P"); + // nothing + } + else if (tok.ttype == 'Y') + { + last = checkIndex(last, "Y"); + if (nval != null) + { + m_years = nval.intValue(); + } + else + { + throw new RuntimeException("IO Error parsing Duration: " + duration); + } + nval = null; + } + else if (tok.ttype == 'M') + { + if (dateMode) + { + last = checkIndex(last, "M"); + if (nval != null) + { + m_months = nval.intValue(); + } + else + { + throw new RuntimeException("IO Error parsing Duration: " + duration); + } + nval = null; + } + else + { + last = checkIndex(last, "m"); + if (nval != null) + { + m_mins = nval.intValue(); + } + else + { + throw new RuntimeException("IO Error parsing Duration: " + duration); + } + nval = null; + } + } + else if (tok.ttype == 'D') + { + last = checkIndex(last, "D"); + if (nval != null) + { + m_days = nval.intValue(); + } + else + { + throw new RuntimeException("IO Error parsing Duration: " + duration); + } + nval = null; + } + else if (tok.ttype == 'T') + { + last = checkIndex(last, "T"); + dateMode = false; + nval = null; + } + else if (tok.ttype == 'H') + { + last = checkIndex(last, "H"); + if (nval != null) + { + m_hours = nval.intValue(); + } + else + { + throw new RuntimeException("IO Error parsing Duration: " + duration); + } + nval = null; + } + else if (tok.ttype == 'S') + { + last = checkIndex(last, "S"); + if (nval != null) + { + m_seconds = nval.intValue(); + m_nanos = (int) ((long) (nval.doubleValue() * 1000000000) % 1000000000); + } + else + { + throw new RuntimeException("IO Error parsing Duration: " + duration); + } + nval = null; + } + else + { + throw new RuntimeException("IO Error parsing Duration: " + duration); + } + } + } + } + catch (IOException e) + { + throw new RuntimeException("IO Error parsing Duration: " + duration); + } + catch (RuntimeException e) + { + throw new RuntimeException("IO Error parsing Duration: " + duration, e); + } + } + } + + /** + * Simple index to check identifiers appear in order + */ + + private int checkIndex(int last, String search) + { + if ((search == null) || (search.length() == 0)) + { + throw new RuntimeException("Null or zero length serach"); + } + int index = s_parse.indexOf(search); + if (index > last) + { + return index; + } + else + { + throw new RuntimeException("Illegal position for identifier " + search); + } + } + + /** + * Create a duration given a date. The duration is between the two dates provided. + * + * Sadly, it works out the duration by incrementing the lower calendar until it matches + * the higher. + */ + + public Duration(Date date) + { + this(date, new Date()); + } + + /** + * Create a duration betweeen two dates expressed as strings. + * Uses the standard XML date form. + * + * @param start - the date at the start of the period + * @param end - the date at the end of the period + */ + + public Duration(String start, String end) + { + this(parseDate(start), parseDate(end)); + } + + + /** + * Helper method to parse eaets from strings + * @param stringDate String + * @return Date + */ + private static Date parseDate(String stringDate) + { + DateFormat df = CachingDateFormat.getDateFormat(); + df.setLenient(true); + Date date; + + ParsePosition pp = new ParsePosition(0); + date = df.parse(stringDate, pp); + if ((pp.getIndex() < stringDate.length()) || (date == null)) + { + date = new Date(); + } + return date; + + } + + /** + * Construct a preiod between the two given dates + * + * @param start_in Date + * @param end_in Date + */ + public Duration(Date start_in, Date end_in) + { + boolean positive = true; + Date start; + Date end; + if (end_in.before(start_in)) + { + start = end_in; + end = start_in; + positive = false; + } + else + { + start = start_in; + end = end_in; + positive = true; + } + Calendar cstart = Calendar.getInstance(); + cstart.setTime(start); + Calendar cend = Calendar.getInstance(); + cend.setTime(end); + + int millis = cend.get(Calendar.MILLISECOND) - cstart.get(Calendar.MILLISECOND); + if (millis < 0) + { + millis += cstart.getActualMaximum(Calendar.MILLISECOND)+1; + } + cstart.add(Calendar.MILLISECOND, millis); + + int seconds = cend.get(Calendar.SECOND) - cstart.get(Calendar.SECOND); + if (seconds < 0) + { + seconds += cstart.getActualMaximum(Calendar.SECOND)+1; + } + cstart.add(Calendar.SECOND, seconds); + + int minutes = cend.get(Calendar.MINUTE) - cstart.get(Calendar.MINUTE); + if (minutes < 0) + { + minutes += cstart.getActualMaximum(Calendar.MINUTE)+1; + } + cstart.add(Calendar.MINUTE, minutes); + + int hours = cend.get(Calendar.HOUR_OF_DAY) - cstart.get(Calendar.HOUR_OF_DAY); + if (hours < 0) + { + hours += cstart.getActualMaximum(Calendar.HOUR_OF_DAY)+1; + } + cstart.add(Calendar.HOUR_OF_DAY, hours); + + int days = cend.get(Calendar.DAY_OF_MONTH) - cstart.get(Calendar.DAY_OF_MONTH); + if (days < 0) + { + days += cstart.getActualMaximum(Calendar.DAY_OF_MONTH)+1; + } + cstart.add(Calendar.DAY_OF_MONTH, days); + + int months = cend.get(Calendar.MONTH) - cstart.get(Calendar.MONTH); + if (months < 0) + { + months += cstart.getActualMaximum(Calendar.MONTH)+1; + } + cstart.add(Calendar.MONTH, months); + + int years = cend.get(Calendar.YEAR) - cstart.get(Calendar.YEAR); + //cstart.add(Calendar.YEAR, years); + + m_positive = positive; + m_years = years; + m_months = months; + m_days = days; + m_hours = hours; + m_mins = minutes; + m_seconds = seconds; + m_nanos = millis * 1000000; + + } + + /** + * Construct a duration from months seconds and nanos + * Checks sign and fixes up seconds and nano. + * Treats year-month abd day-sec as separate chunks + */ + + public Duration(boolean positive_in, long months_in, long seconds_in, long nanos_in) + { + + boolean positive = positive_in; + long months = months_in; + long seconds = seconds_in + nanos_in / 1000000000; + long nanos = nanos_in % 1000000000; + + // Fix up seconds and nanos to be of the same sign + + if ((seconds > 0) && (nanos < 0)) + { + seconds -= 1; + nanos += 1000000000; + } + else if ((seconds < 0) && (nanos > 0)) + { + seconds += 1; + nanos -= 1000000000; + } + + // seconds and nanos now the same sign - sum to test overall sign + + if ((months < 0) && (seconds + nanos < 0)) + { + // switch sign + positive = !positive; + months = -months; + seconds = -seconds; + nanos = -nanos; + } + else if ((months == 0) && (seconds + nanos < 0)) + { + // switch sign + positive = !positive; + months = -months; + seconds = -seconds; + nanos = -nanos; + } + else if ((months > 0) && (seconds + nanos < 0)) + { + throw new RuntimeException("Can not convert to period - incompatible signs for year_to_momth and day_to_second elements"); + } + else if ((months < 0) && (seconds + nanos > 0)) + { + throw new RuntimeException("Can not convert to period - incompatible signs for year_to_momth and day_to_second elements"); + } + else + { + // All +ve + } + + m_positive = positive; + m_years = (int) (months / 12); + m_months = (int) (months % 12); + + m_days = (int) (seconds / (3600 * 24)); + seconds -= m_days * 3600 * 24; + m_hours = (int) (seconds / 3600); + seconds -= m_hours * 3600; + m_mins = (int) (seconds / 60); + seconds -= m_mins * 60; + m_seconds = (int) seconds; + m_nanos = (int) nanos; + + } + + + // Duration arithmetic + + /** + * Add two durations together + */ + + public Duration add(Duration add) + { + + long months = (this.m_positive ? 1 : -1) * this.getTotalMonths() + (add.m_positive ? 1 : -1) * add.getTotalMonths(); + long seconds = (this.m_positive ? 1 : -1) * this.getTotalSeconds() + (add.m_positive ? 1 : -1) * add.getTotalSeconds(); + long nanos = (this.m_positive ? 1 : -1) * this.getTotalNanos() + (add.m_positive ? 1 : -1) * add.getTotalNanos(); + + Duration result = new Duration(true, months, seconds, nanos); + return result; + } + + /** + * Subtract one duration from another + */ + + public Duration subtract(Duration sub) + { + long months = (this.m_positive ? 1 : -1) * this.getTotalMonths() - (sub.m_positive ? 1 : -1) * sub.getTotalMonths(); + long seconds = (this.m_positive ? 1 : -1) * this.getTotalSeconds() - (sub.m_positive ? 1 : -1) * sub.getTotalSeconds(); + long nanos = (this.m_positive ? 1 : -1) * this.getTotalNanos() - (sub.m_positive ? 1 : -1) * sub.getTotalNanos(); + Duration result = new Duration(true, months, seconds, nanos); + return result; + } + + /** + * Negate the duration + */ + + public Duration unaryMinus() + { + Duration result = new Duration(!this.m_positive, this.getTotalMonths(), this.getTotalSeconds(), this.getTotalNanos()); + return result; + } + + /** + * Divide the duration - if year-month drops the day-second part of the duration + */ + + public Duration divide(int d) + { + if (isYearToMonth()) + { + long months = getTotalMonths(); + months /= d; + Duration result = new Duration(m_positive, months, 0, 0); + return result; + } + else + { + long seconds = getTotalSeconds(); + long nanos = (seconds * (1000000000 / d)) % 1000000000; + nanos += getTotalNanos() / d; + seconds /= d; + Duration result = new Duration(m_positive, 0, seconds, nanos); + return result; + } + } + + /** + * Helper method to get the total number of months - year-month + */ + + private long getTotalMonths() + { + return m_years * 12 + m_months; + } + + /** + * Helper method to get the total number of seconds + */ + + private long getTotalSeconds() + { + return m_seconds + m_mins * 60 + m_hours * 3600 + m_days * 3600 * 24; + } + + /** + * Helper method to get the total number of nanos (does not include seconds_ + */ + + private long getTotalNanos() + { + return m_nanos; + } + + /** + * Check if is year-month + */ + + public boolean isYearToMonth() + { + return (m_years != 0) || (m_months != 0); + } + + /** + * Check if is day-sec + */ + + public boolean isDayToSec() + { + return ((m_years == 0) && (m_months == 0)); + } + + /** + * Check if it includes time + */ + + public boolean hasTime() + { + return (m_hours != 0) || (m_mins != 0) || (m_seconds != 0) || (m_nanos != 0); + } + + /** + * Extract the year to month part + */ + + public Duration getYearToMonth() + { + Duration result = new Duration(m_positive, getTotalMonths(), 0, 0); + return result; + } + + /** + * Extract the day to sec part. + */ + + public Duration getDayToYear() + { + Duration result = new Duration(m_positive, 0, getTotalSeconds(), getTotalNanos()); + return result; + } + + /** + * Compare two durations + */ + + public int compareTo(Object o) + { + if (!(o instanceof Duration)) + { + throw new RuntimeException("Can not compare Duration and " + o.getClass().getName()); + } + + Duration d = (Duration) o; + if (this.m_positive != d.m_positive) + { + return (m_positive ? 1 : -1); + } + + if (this.getTotalMonths() != d.getTotalMonths()) + { + return (m_positive ? 1 : -1) * ((int) (this.getTotalMonths() - d.getTotalMonths())); + } + else if (this.getTotalSeconds() != d.getTotalSeconds()) + { + return (m_positive ? 1 : -1) * ((int) (this.getTotalSeconds() - d.getTotalSeconds())); + } + else if (this.getTotalNanos() != d.getTotalNanos()) + { + return (m_positive ? 1 : -1) * ((int) (this.getTotalNanos() - d.getTotalNanos())); + } + else + { + return 0; + } + } + + /** + * @see java.lang.Object#equals(Object) + */ + + public boolean equals(Object o) + { + if (this == o) + return true; + if (!(o instanceof Duration)) + return false; + Duration d = (Duration) o; + return (this.m_positive == d.m_positive) && (this.getTotalMonths() == d.getTotalMonths()) && (this.getTotalSeconds() == d.getTotalSeconds()) && (this.getTotalNanos() == d.getTotalNanos()); + + } + + /** + * @see java.lang.Object#hashCode() + */ + + public int hashCode() + { + int hash = 17; + hash = 37 * hash + (m_positive ? 1 : -1); + hash = 37 * hash + (int) getTotalMonths(); + hash = 37 * hash + (int) getTotalSeconds(); + hash = 37 * hash + (int) getTotalNanos(); + return hash; + } + + /** + * Produce the XML Schema string + * + * @see java.lang.Object#toString() + */ + + public String toString() + { + StringBuffer buffer = new StringBuffer(128); + if (!m_positive) + { + buffer.append("-"); + } + buffer.append("P"); + // Always include years as just P on its own is invalid + buffer.append(m_years).append("Y"); + + if (m_months != 0) + { + buffer.append(m_months).append("M"); + } + if (m_days != 0) + { + buffer.append(m_days).append("D"); + } + if (hasTime()) + { + buffer.append("T"); + if (m_hours != 0) + { + buffer.append(m_hours).append("H"); + } + if (m_mins != 0) + { + buffer.append(m_mins).append("M"); + } + if ((m_seconds != 0) || (m_nanos != 0)) + { + BigDecimal a = new BigDecimal(m_seconds); + BigDecimal b = new BigDecimal(m_nanos); + a = a.add(b.divide(new BigDecimal(1000000000), 9, BigDecimal.ROUND_HALF_EVEN)); + NumberFormat nf = NumberFormat.getInstance(); + buffer.append(nf.format(a)); + buffer.append("S"); + } + + } + + return buffer.toString(); + } + + public String largestComponentformattedString() + { + StringBuffer buffer = new StringBuffer(128); + if (!m_positive) + { + buffer.append("-"); + } + + if (m_years != 0) + { + if (buffer.length() > 0) + buffer.append(" "); + buffer.append(m_years); + buffer.append((m_years == 1) ? " Year" : " Years"); + return buffer.toString(); + } + + if (m_months != 0) + { + if (buffer.length() > 0) + buffer.append(" "); + buffer.append(m_months); + buffer.append((m_months == 1) ? " Month" : " Months"); + return buffer.toString(); + } + + if (m_days != 0) + { + if (buffer.length() > 0) + buffer.append(" "); + buffer.append(m_days); + buffer.append((m_days == 1) ? " Day" : " Days"); + return buffer.toString(); + } + + if (m_hours != 0) + { + if (buffer.length() > 0) + buffer.append(" "); + buffer.append(m_hours); + buffer.append((m_hours == 1) ? " Hour" : " Hours"); + return buffer.toString(); + } + + if (m_mins != 0) + { + if (buffer.length() > 0) + buffer.append(" "); + buffer.append(m_mins); + buffer.append((m_mins == 1) ? " Minute" : " Minutes"); + return buffer.toString(); + } + + + if (buffer.length() > 0) + buffer.append(" "); + BigDecimal a = new BigDecimal(m_seconds); + BigDecimal b = new BigDecimal(m_nanos); + a = a.add(b.divide(new BigDecimal(1000000000), 9, BigDecimal.ROUND_HALF_EVEN)); + NumberFormat nf = NumberFormat.getInstance(); + String formatted = nf.format(a); + buffer.append(formatted); + buffer.append(formatted.equals("1") ? " Second" : " Seconds"); + return buffer.toString(); + + + } + + + /** + * Format in human readable form + * + * TODO: I18n + */ + + public String formattedString() + { + StringBuffer buffer = new StringBuffer(128); + if (!m_positive) + { + buffer.append("-"); + } + if (m_years != 0) + { + if (buffer.length() > 0) + buffer.append(" "); + buffer.append(m_years); + buffer.append((m_years == 1) ? " Year" : " Years"); + + } + if (m_months != 0) + { + if (buffer.length() > 0) + buffer.append(" "); + buffer.append(m_months); + buffer.append((m_months == 1) ? " Month" : " Months"); + } + if (m_days != 0) + { + if (buffer.length() > 0) + buffer.append(" "); + buffer.append(m_days); + buffer.append((m_days == 1) ? " Day" : " Days"); + } + if (hasTime()) + { + if (m_hours != 0) + { + if (buffer.length() > 0) + buffer.append(" "); + buffer.append(m_hours); + buffer.append((m_hours == 1) ? " Hour" : " Hours"); + } + if (m_mins != 0) + { + if (buffer.length() > 0) + buffer.append(" "); + buffer.append(m_mins); + buffer.append((m_mins == 1) ? " Minute" : " Minutes"); + } + if ((m_seconds != 0) || (m_nanos != 0)) + { + if (buffer.length() > 0) + buffer.append(" "); + BigDecimal a = new BigDecimal(m_seconds); + BigDecimal b = new BigDecimal(m_nanos); + a = a.add(b.divide(new BigDecimal(1000000000), 9, BigDecimal.ROUND_HALF_EVEN)); + NumberFormat nf = NumberFormat.getInstance(); + String formatted = nf.format(a); + buffer.append(formatted); + buffer.append(formatted.equals("1") ? " Second" : " Seconds"); + } + + } + + return buffer.toString(); + } + + + /** + * TODO: Tests that should be moved into a unit test + * + * @param args String[] + */ + public static void main(String[] args) + { + Duration diff = new Duration("2002-04-02T01:01:01", "2003-03-01T00:00:00"); + System.out.println("Diff " + diff); + + try + { + Duration test = new Duration("P"); + System.out.println("Just P" + test); + } + catch (RuntimeException e) + { + e.printStackTrace(); + } + + try + { + Duration test2 = new Duration("P Jones"); + System.out.println("P Jones" + test2); + } + catch (RuntimeException e) + { + e.printStackTrace(); + } + + try + { + Duration test2 = new Duration("P12Y Jones"); + System.out.println("P Jones" + test2); + } + catch (RuntimeException e) + { + e.printStackTrace(); + } + + try + { + Duration test = new Duration("PPPPPPPPPPPPPP"); + System.out.println("Just many P" + test); + } + catch (RuntimeException e) + { + e.printStackTrace(); + } + + try + { + Duration test = new Duration("PY"); + System.out.println("PY" + test); + } + catch (RuntimeException e) + { + e.printStackTrace(); + } + + try + { + Duration test = new Duration("PM"); + System.out.println("PM" + test); + } + catch (RuntimeException e) + { + e.printStackTrace(); + } + + try + { + Duration test = new Duration("PP"); + System.out.println("PP" + test); + } + catch (RuntimeException e) + { + e.printStackTrace(); + } + + Date now = new Date(); + Calendar c = Calendar.getInstance(); + c.setTime(now); + c.add(Calendar.YEAR, -1); + c.add(Calendar.MONTH, +2); + c.add(Calendar.DAY_OF_MONTH, -3); + c.add(Calendar.HOUR_OF_DAY, +4); + c.add(Calendar.MINUTE, -5); + c.add(Calendar.SECOND, +6); + c.add(Calendar.MILLISECOND, -7); + + diff = new Duration(c.getTime(), now); + System.out.println("V: " + diff); + + Duration diff2 = new Duration(now, c.getTime()); + System.out.println("V: " + diff2); + + Duration a1 = new Duration("P2Y6M"); + Duration a2 = new Duration("P1DT2H3M1.5S"); + + Duration d = new Duration("P2Y6M5DT12H35M30.100S"); + System.out.println("V: " + d); + System.out.println("F: " + d.formattedString()); + System.out.println(" D: " + d.divide(2)); + System.out.println(" +: " + d.add(a1)); + System.out.println(" +: " + d.add(a1.add(a2))); + d = new Duration("P1DT2H3M1.5S"); + System.out.println("V: " + d); + System.out.println("F: " + d.formattedString()); + System.out.println(" D: " + d.divide(2)); + System.out.println(" +: " + d.add(a1)); + System.out.println(" +: " + d.add(a1.add(a2))); + d = new Duration("PT1.5S"); + System.out.println("V: " + d); + System.out.println("F: " + d.formattedString()); + System.out.println(" D: " + d.divide(2)); + System.out.println(" +: " + d.add(a1)); + System.out.println(" +: " + d.add(a1.add(a2))); + d = new Duration("P20M"); + System.out.println("V: " + d); + System.out.println("F: " + d.formattedString()); + System.out.println(" D: " + d.divide(2)); + System.out.println(" +: " + d.add(a1)); + System.out.println(" +: " + d.add(a1.add(a2))); + d = new Duration("P0Y20M0D"); + System.out.println("V: " + d); + System.out.println("F: " + d.formattedString()); + System.out.println(" D: " + d.divide(2)); + System.out.println(" +: " + d.add(a1)); + System.out.println(" +: " + d.add(a1.add(a2))); + d = new Duration("-P60D"); + System.out.println("V: " + d); + System.out.println("F: " + d.formattedString()); + System.out.println(" D: " + d.divide(10)); + System.out.println(" +: " + d.add(a2)); + //System.out.println(" +: " + d.add(a1)); + + + d = new Duration("P1H"); + System.out.println("V: " + d); + System.out.println("F: " + d.formattedString()); + System.out.println(" D: " + d.divide(10)); + System.out.println(" +: " + d.add(a2)); + + d = new Duration("PT1H"); + System.out.println("V: " + d); + System.out.println("F: " + d.formattedString()); + System.out.println(" D: " + d.divide(10)); + System.out.println(" +: " + d.add(a2)); + + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/datatype/TypeConversionException.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/datatype/TypeConversionException.java new file mode 100644 index 0000000000..a2818aff6c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/datatype/TypeConversionException.java @@ -0,0 +1,50 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository.datatype; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Base Exception of Type Converter Exceptions. + * + * @author David Caruana + */ +@AlfrescoPublicApi +public class TypeConversionException extends RuntimeException +{ + private static final long serialVersionUID = 3257008761007847733L; + + public TypeConversionException(String msg) + { + super(msg); + } + + public TypeConversionException(String msg, Throwable cause) + { + super(msg, cause); + } + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/repository/datatype/TypeConverter.java b/data-model/src/main/java/org/alfresco/service/cmr/repository/datatype/TypeConverter.java new file mode 100644 index 0000000000..3592bcbae7 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/repository/datatype/TypeConverter.java @@ -0,0 +1,614 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository.datatype; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.springframework.extensions.surf.util.ParameterCheck; + + +/** + * Support for generic conversion between types. + * + * Additional conversions may be added. + * + * Direct conversion and two stage conversions via Number are supported. We do + * not support conversion by any route at the moment + */ +@AlfrescoPublicApi +public class TypeConverter +{ + + /** + * General conversion method to Object types (note it cannot support + * conversion to primary types due the restrictions of reflection. Use the + * static conversion methods to primitive types) + * + * @param propertyType - the target property type + * @param value - the value to be converted + * @return - the converted value as the correct type + */ + public final Object convert(DataTypeDefinition propertyType, Object value) + { + ParameterCheck.mandatory("Property type definition", propertyType); + + // Convert property type to java class + Class javaClass = null; + String javaClassName = propertyType.getJavaClassName(); + try + { + javaClass = Class.forName(javaClassName); + } + catch (ClassNotFoundException e) + { + throw new DictionaryException("Java class " + javaClassName + " of property type " + propertyType.getName() + " is invalid", e); + } + + return convert(javaClass, value); + } + + /** + * General conversion method to Object types (note it cannot support + * conversion to primary types due the restrictions of reflection. Use the + * static conversion methods to primitive types) + * + * @param The target type for the result of the conversion + * @param c - a class for the target type + * @param value - the value to be converted + * @return - the converted value as the correct type + * @throws TypeConversionException if the conversion cannot be performed + */ + public final T convert(Class c, Object value) + { + if(value == null) + { + return null; + } + + // Primative types + if (c.isPrimitive()) + { + // We can not suport primitive type conversion + throw new TypeConversionException("Can not convert direct to primitive type " + c.getName()); + } + + // Check if we already have the correct type + if (c.isInstance(value)) + { + return c.cast(value); + } + + // Find the correct conversion - if available and do the converiosn + Converter converter = getConverter(value, c); + if (converter == null) + { + throw new TypeConversionException( + "There is no conversion registered for the value: \n" + + " value class: " + value.getClass().getName() + "\n" + + " to class: " + c.getName() + "\n" + + " value: " + value.toString()); + } + + return converter.convert(value); + } + + /** + * General conversion method to convert collection contents to the specified + * type. Wrapper around the Collection version for arrays. + * + * @param propertyType - the target property type + * @param values - the value to be converted + * @return - the converted value as the correct type + * @throws DictionaryException if the property type's registered java class is invalid + * @throws TypeConversionException if the conversion cannot be performed + */ + public final Collection convert(DataTypeDefinition propertyType, Object[] values) + { + if(values == null) { + return convert(propertyType, (Collection)null); + } else { + // Turn the array into a Collection, then convert as that + ArrayList c = new ArrayList(); + c.ensureCapacity(values.length); + for(Object v : values) { + c.add(v); + } + // Convert + return convert(propertyType, c); + } + } + + /** + * General conversion method to convert collection contents to the specified + * type. + * + * @param propertyType - the target property type + * @param values - the value to be converted + * @return - the converted value as the correct type + * @throws DictionaryException if the property type's registered java class is invalid + * @throws TypeConversionException if the conversion cannot be performed + */ + public final Collection convert(DataTypeDefinition propertyType, Collection values) + { + ParameterCheck.mandatory("Property type definition", propertyType); + + // Convert property type to java class + Class javaClass = null; + String javaClassName = propertyType.getJavaClassName(); + try + { + javaClass = Class.forName(javaClassName); + } + catch (ClassNotFoundException e) + { + throw new DictionaryException("Java class " + javaClassName + " of property type " + propertyType.getName() + " is invalid", e); + } + + return convert(javaClass, values); + } + + /** + * General conversion method to convert collection contents to the specified + * type. + * + * @param The target type for the result of the conversion + * @param c - a class for the target type + * @param values - the collection to be converted + * @return - the converted collection + * @throws TypeConversionException if the conversion cannot be performed + */ + public final Collection convert(Class c, Collection values) + { + if(values == null) + { + return null; + } + + Collection converted = new ArrayList(values.size()); + for (Object value : values) + { + converted.add(convert(c, value)); + } + + return converted; + } + + /** + * Get the boolean value for the value object + * May have conversion failure + * + * @param value Object + * @return boolean + */ + public final boolean booleanValue(Object value) + { + return convert(Boolean.class, value).booleanValue(); + } + + /** + * Get the char value for the value object + * May have conversion failure + * + * @param value Object + * @return char + */ + public final char charValue(Object value) + { + return convert(Character.class, value).charValue(); + } + + /** + * Get the byte value for the value object + * May have conversion failure + * + * @param value Object + * @return byte + */ + public final byte byteValue(Object value) + { + if (value instanceof Number) + { + return ((Number) value).byteValue(); + } + return convert(Byte.class, value).byteValue(); + } + + /** + * Get the short value for the value object + * May have conversion failure + * + * @param value Object + * @return short + */ + public final short shortValue(Object value) + { + if (value instanceof Number) + { + return ((Number) value).shortValue(); + } + return convert(Short.class, value).shortValue(); + } + + /** + * Get the int value for the value object + * May have conversion failure + * + * @param value Object + * @return int + */ + public final int intValue(Object value) + { + if (value instanceof Number) + { + return ((Number) value).intValue(); + } + return convert(Integer.class, value).intValue(); + } + + /** + * Get the long value for the value object + * May have conversion failure + * + * @param value Object + * @return long + */ + public final long longValue(Object value) + { + if (value instanceof Number) + { + return ((Number) value).longValue(); + } + return convert(Long.class, value).longValue(); + } + + /** + * Get the bollean value for the value object + * May have conversion failure + * + * @param value Object + * @return float + */ + public final float floatValue(Object value) + { + if (value instanceof Number) + { + return ((Number) value).floatValue(); + } + return convert(Float.class, value).floatValue(); + } + + /** + * Get the bollean value for the value object + * May have conversion failure + * + * @param value Object + * @return double + */ + public final double doubleValue(Object value) + { + if (value instanceof Number) + { + return ((Number) value).doubleValue(); + } + return convert(Double.class, value).doubleValue(); + } + + /** + * Is the value multi valued + * + * @param value Object + * @return true - if the underlyinf is a collection of values and not a singole value + */ + public final boolean isMultiValued(Object value) + { + return (value instanceof Collection); + } + + /** + * Get the number of values represented + * + * @param value Object + * @return 1 for normal values and the size of the collection for MVPs + */ + public final int size(Object value) + { + if (value instanceof Collection) + { + return ((Collection) value).size(); + } + else + { + return 1; + } + } + + /** + * Get a collection for the passed value + * + * @param value Object + * @return Collection + */ + private final Collection createCollection(Object value) + { + Collection coll; + if (isMultiValued(value)) + { + coll = (Collection) value; + } + else + { + ArrayList list = new ArrayList(1); + list.add(value); + coll = list; + } + return coll; + } + + /** + * Get a collection for the passed value converted to the specified type + * + * @param value Object + * @return Collection + */ + public final Collection getCollection(Class c, Object value) + { + Collection coll = createCollection(value); + return convert(c, coll); + } + + /** + * Add a converter to the list of those available + */ + public final void addConverter(Class source, Class destination, Converter converter) + { + Map, Converter> map = conversions.get(source); + if (map == null) + { + map = new HashMap, Converter>(); + conversions.put(source, map); + } + map.put(destination, converter); + } + + /** + * Add a dynamic two stage converter + */ + public final Converter addDynamicTwoStageConverter(Class source, Class intermediate, Class destination) + { + Converter converter = new TypeConverter.DynamicTwoStageConverter(source, intermediate, destination); + addConverter(source, destination, converter); + return converter; + } + + /** + * Find conversion for the specified object + * + * Note: Takes into account the class of the object and any interfaces it may + * also support. + * + */ + @SuppressWarnings("unchecked") + public final Converter getConverter(Object value, Class dest) + { + Converter converter = null; + if (value == null) + { + return null; + } + + // find via class of value + Class valueClass = value.getClass(); + converter = (Converter) getConverter(valueClass, dest); + if (converter != null) + { + return converter; + } + + // find via supported interfaces of value + do + { + Class[] ifClasses = valueClass.getInterfaces(); + for (Class ifClass : ifClasses) + { + converter = (Converter) getConverter(ifClass, dest); + if (converter != null) + { + return converter; + } + } + valueClass = valueClass.getSuperclass(); + } + while (valueClass != null); + + return null; + } + + public Map, Map, Converter>> getConverters() + { + return conversions; + } + + /** + * Find a conversion for a specific Class + * + * @return conversion + */ + @SuppressWarnings("unchecked") + public Converter getConverter(Class source, Class dest) + { + Converter converter = null; + Class clazz = source; + do + { + Map, Converter> map = conversions.get(clazz); + if (map == null) + { + continue; + } + converter = (Converter) map.get(dest); + + if (converter == null) + { + // attempt to establish converter from source to dest via Number + Converter first = (Converter) map.get(Number.class); + Converter second = null; + if (first != null) + { + map = conversions.get(Number.class); + if (map != null) + { + second = (Converter) map.get(dest); + } + } + if (second != null) + { + converter = new TwoStageConverter(first, second); + } + } + } + while ((converter == null) && ((clazz = clazz.getSuperclass()) != null)); + + return converter; + } + + /** + * Map of conversion + */ + private Map, Map, Converter>> conversions = new HashMap, Map, Converter>>(); + + + // Support for pluggable conversions + + /** + * Conversion interface + * + * @author andyh + * + * @param F From type + * @param T To type + */ + @AlfrescoPublicApi + public interface Converter + { + public T convert(F source); + } + + /** + * Support for chaining conversions + * + * @author andyh + * + * @param F From Type + * @param I Intermediate type + * @param T To Type + */ + @AlfrescoPublicApi + public static class TwoStageConverter implements Converter + { + Converter first; + + Converter second; + + TwoStageConverter(Converter first, Converter second) + { + this.first = first; + this.second = second; + } + + public T convert(F source) + { + return second.convert(first.convert(source)); + } + } + + /** + * Support for chaining conversions + * + * @author David Caruana + * + * @param F From Type + * @param I Intermediate type + * @param T To Type + */ + @AlfrescoPublicApi + protected class DynamicTwoStageConverter implements Converter + { + Class from; + Class intermediate; + Class to; + + DynamicTwoStageConverter(Class from, Class intermediate, Class to) + { + this.from = from; + this.intermediate = intermediate; + this.to = to; + } + + /** + * @return from class + */ + public Class getFrom() + { + return from; + } + + /** + * @return intermediate class + */ + public Class getIntermediate() + { + return intermediate; + } + + /** + * @return to class + */ + public Class getTo() + { + return to; + } + + public T convert(F source) + { + Converter iConverter = TypeConverter.this.getConverter(from, intermediate); + Converter tConverter = TypeConverter.this.getConverter(intermediate, to); + if (iConverter == null || tConverter == null) + { + throw new TypeConversionException("Cannot convert from " + from.getName() + " to " + to.getName()); + } + + I iValue = iConverter.convert(source); + return tConverter.convert(iValue); + } + } + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/BasicSearchParameters.java b/data-model/src/main/java/org/alfresco/service/cmr/search/BasicSearchParameters.java new file mode 100644 index 0000000000..d6cb10047d --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/BasicSearchParameters.java @@ -0,0 +1,49 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.util.List; +import java.util.Locale; + +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.SearchParameters.SortDefinition; + +/** + * These are high level parameters, for use when searching. + * + * @author Gethin James + * @since 5.0 + */ +public interface BasicSearchParameters +{ + + public String getLanguage(); + public String getQuery(); + public List getStores(); + public List getLocales(); + public List getSortDefinitions(); + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/FacetFormat.java b/data-model/src/main/java/org/alfresco/service/cmr/search/FacetFormat.java new file mode 100644 index 0000000000..97c23a4bd4 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/FacetFormat.java @@ -0,0 +1,31 @@ +/*- + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2017 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +public enum FacetFormat +{ + V1,V2 +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/FieldHighlightParameters.java b/data-model/src/main/java/org/alfresco/service/cmr/search/FieldHighlightParameters.java new file mode 100644 index 0000000000..6b1de6d495 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/FieldHighlightParameters.java @@ -0,0 +1,98 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import org.alfresco.api.AlfrescoPublicApi; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Parameters used for search hightlighting that are Field Specific + */ + +@AlfrescoPublicApi +public class FieldHighlightParameters extends HighlightParameters +{ + private final String field; + + @JsonCreator + public FieldHighlightParameters( + @JsonProperty("field") String field, + @JsonProperty("snippetCount") Integer snippetCount, + @JsonProperty("fragmentSize") Integer fragmentSize, + @JsonProperty("mergeContiguous") Boolean mergeContiguous, + @JsonProperty("prefix") String prefix, + @JsonProperty("postfix") String postfix) + { + super(snippetCount, fragmentSize, mergeContiguous, prefix, postfix); + this.field = field; + } + + @Override + public String toString() + { + return "FieldHighlightParameters{" + + "snippetCount=" + snippetCount + + ", fragmentSize=" + fragmentSize + + ", mergeContiguous=" + mergeContiguous + + ", prefix='" + prefix + '\'' + + ", postfix='" + postfix + '\'' + + ", field='" + field + '\'' + + '}'; + } + + public String getField() + { + return field; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + if (!super.equals(o)) + return false; + + FieldHighlightParameters that = (FieldHighlightParameters) o; + + if (field != null ? !field.equals(that.field) : that.field != null) + return false; + + return true; + } + + @Override + public int hashCode() + { + int result = super.hashCode(); + result = 31 * result + (field != null ? field.hashCode() : 0); + return result; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/GeneralHighlightParameters.java b/data-model/src/main/java/org/alfresco/service/cmr/search/GeneralHighlightParameters.java new file mode 100644 index 0000000000..3aae4d8768 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/GeneralHighlightParameters.java @@ -0,0 +1,128 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.util.List; + +import org.alfresco.api.AlfrescoPublicApi; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Parameters used for search hightlighting that apply to all fields + */ + +@AlfrescoPublicApi +public class GeneralHighlightParameters extends HighlightParameters +{ + private final Integer maxAnalyzedChars; + private final Boolean usePhraseHighlighter; + + private final List fields; + + @JsonCreator + public GeneralHighlightParameters( + @JsonProperty("snippetCount") Integer snippetCount, + @JsonProperty("fragmentSize") Integer fragmentSize, + @JsonProperty("mergeContiguous") Boolean mergeContiguous, + @JsonProperty("prefix") String prefix, + @JsonProperty("postfix") String postfix, + @JsonProperty("maxAnalyzedChars") Integer maxAnalyzedChars, + @JsonProperty("usePhraseHighlighter") Boolean usePhraseHighlighter, + @JsonProperty("fields") List fields) + { + super(snippetCount, fragmentSize, mergeContiguous, prefix, postfix); + this.maxAnalyzedChars = maxAnalyzedChars; + this.usePhraseHighlighter = usePhraseHighlighter; + this.fields = fields; + } + + @Override + public String toString() + { + return "GeneralHighlightParameters{" + + "snippetCount=" + snippetCount + + ", fragmentSize=" + fragmentSize + + ", mergeContiguous=" + mergeContiguous + + ", prefix='" + prefix + '\'' + + ", postfix='" + postfix + '\'' + + ", maxAnalyzedChars=" + maxAnalyzedChars + + ", usePhraseHighlighter=" + usePhraseHighlighter + + ", fields=" + fields + + '}'; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + if (!super.equals(o)) + return false; + + GeneralHighlightParameters that = (GeneralHighlightParameters) o; + + if (getMaxAnalyzedChars() != null ? !getMaxAnalyzedChars().equals(that.getMaxAnalyzedChars()) : that.getMaxAnalyzedChars() != null) + return false; + if (getUsePhraseHighlighter() != null ? + !getUsePhraseHighlighter().equals(that.getUsePhraseHighlighter()) : + that.getUsePhraseHighlighter() != null) + return false; + if (getFields() != null ? !getFields().equals(that.getFields()) : that.getFields() != null) + return false; + + return true; + } + + @Override + public int hashCode() + { + int result = super.hashCode(); + result = 31 * result + (getMaxAnalyzedChars() != null ? getMaxAnalyzedChars().hashCode() : 0); + result = 31 * result + (getUsePhraseHighlighter() != null ? getUsePhraseHighlighter().hashCode() : 0); + result = 31 * result + (getFields() != null ? getFields().hashCode() : 0); + return result; + } + + public Integer getMaxAnalyzedChars() + { + return maxAnalyzedChars; + } + + public Boolean getUsePhraseHighlighter() + { + return usePhraseHighlighter; + } + + public List getFields() + { + return fields; + } + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/HighlightParameters.java b/data-model/src/main/java/org/alfresco/service/cmr/search/HighlightParameters.java new file mode 100644 index 0000000000..1068d31154 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/HighlightParameters.java @@ -0,0 +1,126 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Parameters used for search hightlighting. + */ + +@AlfrescoPublicApi +public abstract class HighlightParameters +{ + final Integer snippetCount; + final Integer fragmentSize; + + final Boolean mergeContiguous; + + final String prefix; + final String postfix; + + public HighlightParameters(Integer snippetCount, Integer fragmentSize, + Boolean mergeContiguous, String prefix, String postfix) + { + this.snippetCount = snippetCount; + this.fragmentSize = fragmentSize; + this.mergeContiguous = mergeContiguous; + this.prefix = prefix; + this.postfix = postfix; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + HighlightParameters that = (HighlightParameters) o; + + if (snippetCount != null ? !snippetCount.equals(that.snippetCount) : that.snippetCount != null) + return false; + if (fragmentSize != null ? !fragmentSize.equals(that.fragmentSize) : that.fragmentSize != null) + return false; + if (mergeContiguous != null ? !mergeContiguous.equals(that.mergeContiguous) : that.mergeContiguous != null) + return false; + if (prefix != null ? !prefix.equals(that.prefix) : that.prefix != null) + return false; + if (postfix != null ? !postfix.equals(that.postfix) : that.postfix != null) + return false; + + return true; + } + + @Override + public int hashCode() + { + int result = snippetCount != null ? snippetCount.hashCode() : 0; + result = 31 * result + (fragmentSize != null ? fragmentSize.hashCode() : 0); + result = 31 * result + (mergeContiguous != null ? mergeContiguous.hashCode() : 0); + result = 31 * result + (prefix != null ? prefix.hashCode() : 0); + result = 31 * result + (postfix != null ? postfix.hashCode() : 0); + return result; + } + + @Override + public String toString() + { + return "HighlightParameters{" + + "snippetCount=" + snippetCount + + ", fragmentSize=" + fragmentSize + + ", mergeContiguous=" + mergeContiguous + + ", prefix='" + prefix + '\'' + + ", postfix='" + postfix + '\'' + + '}'; + } + + public Integer getSnippetCount() + { + return snippetCount; + } + + public Integer getFragmentSize() + { + return fragmentSize; + } + + public Boolean getMergeContiguous() + { + return mergeContiguous; + } + + public String getPrefix() + { + return prefix; + } + + public String getPostfix() + { + return postfix; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/Interval.java b/data-model/src/main/java/org/alfresco/service/cmr/search/Interval.java new file mode 100644 index 0000000000..ed872b49da --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/Interval.java @@ -0,0 +1,78 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2017 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.util.HashSet; +import java.util.Set; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Parameters used for a search Interval. + */ +public class Interval +{ + private final String field; + private final String label; + private final Set sets; + + @JsonCreator + public Interval( + @JsonProperty("field") String field, + @JsonProperty("label") String label, + @JsonProperty("sets") Set sets) + { + this.field = field; + this.label = label; + this.sets = sets == null ? new HashSet() :sets; + } + + public String getField() + { + return field; + } + + public String getLabel() + { + return label; + } + + public Set getSets() + { + return sets; + } + + @Override + public String toString() + { + return "Interval{" + + "field='" + field + '\'' + + ", label='" + label + '\'' + + ", sets=" + sets + + '}'; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/IntervalParameters.java b/data-model/src/main/java/org/alfresco/service/cmr/search/IntervalParameters.java new file mode 100644 index 0000000000..75f579aff8 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/IntervalParameters.java @@ -0,0 +1,72 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2017 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.util.List; +import java.util.Set; + +import org.alfresco.api.AlfrescoPublicApi; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Parameters used for search Intervals. + */ +@AlfrescoPublicApi +public class IntervalParameters +{ + private final Set sets; + private final List intervals; + + @JsonCreator + public IntervalParameters( + @JsonProperty("sets") Set sets, + @JsonProperty("intervals") List intervals) + { + this.sets = sets; + this.intervals = intervals; + } + + public Set getSets() + { + return sets; + } + + public List getIntervals() + { + return intervals; + } + + @Override + public String toString() + { + return "IntervalParameters{" + + "sets=" + sets + + ", intervals=" + intervals + + '}'; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/IntervalSet.java b/data-model/src/main/java/org/alfresco/service/cmr/search/IntervalSet.java new file mode 100644 index 0000000000..bc20f66d24 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/IntervalSet.java @@ -0,0 +1,172 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2017 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import org.alfresco.api.AlfrescoPublicApi; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Parameters used for search Interval sets. + */ +@AlfrescoPublicApi +public class IntervalSet +{ + private final String start; + private final String end; + private String label; + private final boolean startInclusive; + private final boolean endInclusive; + + @JsonCreator + public IntervalSet( + @JsonProperty("start") String start, + @JsonProperty("end") String end, + @JsonProperty("label") String label, + @JsonProperty("startInclusive") Boolean startInclusive, + @JsonProperty("endInclusive") Boolean endInclusive) + { + this.start = start; + this.end = end; + this.label = label; + this.startInclusive = startInclusive == null ? true : startInclusive; + this.endInclusive = endInclusive == null ? true : endInclusive; + } + + public String getStart() + { + return start; + } + + public String getEnd() + { + return end; + } + + public String getLabel() + { + return label; + } + + public void setLabel(String label) + { + this.label = label; + } + + public boolean isStartInclusive() + { + return startInclusive; + } + + public boolean isEndInclusive() + { + return endInclusive; + } + + public String toParam() + { + StringBuilder sb = new StringBuilder("{!afts"); + if (label != null && !label.isEmpty()) + { + sb.append(" key="+label); + } + sb.append("}") + .append(toRange()); + return sb.toString(); + } + + public String toRange() + { + StringBuilder sb = new StringBuilder(""); + sb.append(startInclusive?"[":"(") + .append(start) + .append(","+end) + .append(endInclusive?"]":")"); + return sb.toString(); + } + + /** + * Returns a valid AFTS query for this Interval Set + * @return a query + */ + public String toAFTSQuery() + { + StringBuilder sb = new StringBuilder(""); + sb.append(startInclusive?"[":"<") + .append("\"").append(start).append("\"") + .append(" TO ") + .append("\"").append(end).append("\"") + .append(endInclusive?"]":">"); + return sb.toString(); + } + + @Override + public String toString() + { + return "IntervalSet{" + + "start=" + start + + ", end=" + end + + ", label='" + label + '\'' + + ", startInclusive=" + startInclusive + + ", endInclusive=" + endInclusive + + '}'; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + IntervalSet that = (IntervalSet) o; + + if (startInclusive != that.startInclusive) + return false; + if (endInclusive != that.endInclusive) + return false; + if (start != null ? !start.equals(that.start) : that.start != null) + return false; + if (end != null ? !end.equals(that.end) : that.end != null) + return false; + if (label != null ? !label.equals(that.label) : that.label != null) + return false; + + return true; + } + + @Override + public int hashCode() + { + int result = start != null ? start.hashCode() : 0; + result = 31 * result + (end != null ? end.hashCode() : 0); + result = 31 * result + (startInclusive ? 1 : 0); + result = 31 * result + (endInclusive ? 1 : 0); + return result; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/LimitBy.java b/data-model/src/main/java/org/alfresco/service/cmr/search/LimitBy.java new file mode 100644 index 0000000000..50f8107395 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/LimitBy.java @@ -0,0 +1,52 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Enum to describe how the maximum size of the returned result set should be determined. + * + * @author Andy Hind + */ +@AlfrescoPublicApi +public enum LimitBy +{ + /** + * The final number of search results is not important. + */ + UNLIMITED, + /** + * Limit the total number of search results returned after pruning by permissions. + */ + FINAL_SIZE, + /** + * Limit the number of results that will be passed through for permission checks.
    + * Used internally to prevent excessive permission checking + * (see property lucene.query.maxInitialSearchResults). + */ + NUMBER_OF_PERMISSION_EVALUATIONS; +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/NamedQueryParameterDefinition.java b/data-model/src/main/java/org/alfresco/service/cmr/search/NamedQueryParameterDefinition.java new file mode 100644 index 0000000000..c66f71b392 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/NamedQueryParameterDefinition.java @@ -0,0 +1,49 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.namespace.QName; + +@AlfrescoPublicApi +public interface NamedQueryParameterDefinition +{ + + /** + * Get the name of this parameter. It could be used as the well known name for the parameter. + * + * Not null + * + * @return QName + */ + public QName getQName(); + + /** + * Get the query parameter definition + * @return QueryParameterDefinition + */ + public QueryParameterDefinition getQueryParameterDefinition(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/PermissionEvaluationMode.java b/data-model/src/main/java/org/alfresco/service/cmr/search/PermissionEvaluationMode.java new file mode 100644 index 0000000000..00d2a953b9 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/PermissionEvaluationMode.java @@ -0,0 +1,39 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Enum to control how permissions are evaluated. + * + * @author Andy Hind + */ +@AlfrescoPublicApi +public enum PermissionEvaluationMode +{ + EAGER, NONE; +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/QueryConsistency.java b/data-model/src/main/java/org/alfresco/service/cmr/search/QueryConsistency.java new file mode 100644 index 0000000000..66b6fd8584 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/QueryConsistency.java @@ -0,0 +1,35 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +/** + * @author Andy + * + */ +public enum QueryConsistency +{ + EVENTUAL, TRANSACTIONAL, DEFAULT, TRANSACTIONAL_IF_POSSIBLE, HYBRID; +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/QueryParameter.java b/data-model/src/main/java/org/alfresco/service/cmr/search/QueryParameter.java new file mode 100644 index 0000000000..43406e8339 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/QueryParameter.java @@ -0,0 +1,66 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.io.Serializable; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.namespace.QName; + +/** + * Encapsulates a query parameter + * + * @author andyh + * + */ +@AlfrescoPublicApi +public class QueryParameter +{ + private QName qName; + + private Serializable value; + + public QueryParameter(QName qName, Serializable value) + { + this.qName = qName; + this.value = value; + } + + public QName getQName() + { + return qName; + } + + + public Serializable getValue() + { + return value; + } + + + + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/QueryParameterDefinition.java b/data-model/src/main/java/org/alfresco/service/cmr/search/QueryParameterDefinition.java new file mode 100644 index 0000000000..34f8b15780 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/QueryParameterDefinition.java @@ -0,0 +1,67 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +@AlfrescoPublicApi +public interface QueryParameterDefinition extends NamedQueryParameterDefinition +{ + /** + * This parameter may apply to a well known property type. + * + * May be null + * + * @return PropertyDefinition + */ + public PropertyDefinition getPropertyDefinition(); + + /** + * Get the property type definition for this parameter. + * It could come from the property type definition if there is one + * + * Not null + * + * @return DataTypeDefinition + */ + public DataTypeDefinition getDataTypeDefinition(); + + /** + * Get the default value for this parameter. + * + * @return String + */ + public String getDefault(); + + /** + * Has this parameter got a default value? + * + * @return boolean + */ + public boolean hasDefaultValue(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/RangeParameters.java b/data-model/src/main/java/org/alfresco/service/cmr/search/RangeParameters.java new file mode 100644 index 0000000000..f6735318ad --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/RangeParameters.java @@ -0,0 +1,228 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2017 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.util.Collections; +import java.util.List; + +import org.alfresco.api.AlfrescoPublicApi; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Parameters used for search range. + */ +@AlfrescoPublicApi +public class RangeParameters +{ + private final String field; + private final String start; + private final String end; + private final String gap; + private final boolean hardend; + private final List other; + private final List include; + private final String label; + private final List excludeFilters; + + /** + * Constructor. + * @param field + * @param minCount + * @param start + * @param end + * @param gap + * @param hardend + * @param other can have one of the following values: before,after,between,none + * @param include can have one of the following values: lower,upper,edge,outer,all + * @param label + * @param excludeFilters + */ + @JsonCreator + public RangeParameters(@JsonProperty("field") String field, + @JsonProperty("start") String start, + @JsonProperty("end") String end, + @JsonProperty("gap") String gap, + @JsonProperty("hardend") boolean hardend, + @JsonProperty("other")List other, + @JsonProperty("include")List include, + @JsonProperty("label") String label, + @JsonProperty("excludeFilters")List excludeFilters) + { + super(); + this.field = field; + this.start = start; + this.end = end; + this.gap = gap; + this.hardend = hardend; + this.other = other == null? Collections.emptyList():other; + this.include = include == null? Collections.emptyList():include; + this.label = label; + this.excludeFilters = excludeFilters == null? Collections.emptyList():excludeFilters; + } + + public String getField() + { + return field; + } + public String getStart() + { + return start; + } + public String getEnd() + { + return end; + } + public String getGap() + { + return gap; + } + public boolean isHardend() + { + return hardend; + } + public List getOther() + { + return other; + } + public List getInclude() + { + return include; + } + public String getLabel() + { + return label; + } + + public List getExcludeFilters() + { + return excludeFilters; + } + + public String getRangeFirstBucketStartInclusive() + { + if(include != null && !include.isEmpty()) + { + for(String startInc : include) + { + switch (startInc) + { + case "before": + break; + case "edge": + return "["; + case "lower": + return "["; + default: + } + } + return "<"; + } + return "["; + } + public String getRangeFirstBucketEndInclusive() + { + if(include != null && !include.isEmpty()) + { + for(String startInc : include) + { + switch (startInc) + { + case "upper": + return "]"; + case "outer": + if(other != null && (other.contains("before") || other.contains("after"))) + { + return "]"; + } + break; + default: + break; + } + } + } + return ">"; + } + + + public String getRangeBucketStartInclusive() + { + if(include != null && !include.isEmpty()) + { + for(String key : include) + { + switch (key) + { + case "lower": + return "["; + default: + break; + } + } + return "<"; + } + return "["; + } + public String getRangeBucketEndInclusive() + { + if(include != null && !include.isEmpty()) + { + for(String key : include) + { + switch (key) + { + case "upper": + return "]"; + default: + break; + } + } + } + return ">"; + } + + public String getRangeLastBucketEndInclusive() + { + if(include != null && !include.isEmpty()) + { + for(String key : include) + { + switch (key) + { + case "edge": + return "]"; + case "upper": + return "]"; + default: + break; + } + } + return ">"; + } + return "]"; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSet.java b/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSet.java new file mode 100644 index 0000000000..0275223243 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSet.java @@ -0,0 +1,47 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import org.alfresco.api.AlfrescoPublicApi; + + +/** + * This is the common interface for both row (Alfresco node) and column (CMIS style property or function) based results. + * The meta-data for the results sets contains the detailed info on what columns are available. For row based result + * sets there is no selector - all the nodes returned do not have to have a specific type or aspect. For example, an FTS + * search on properties of type d:content has no type constraint implied or otherwise. Searches against properties have + * an implied type, but as there can be more than one property -> more than one type or aspect implied (eg via OR in FTS + * or lucene) they are ignored An iterable result set from a searcher query. Implementations must implement the + * indexes for row lookup as zero-based. + * + * @author andyh + */ +@AlfrescoPublicApi +public interface ResultSet extends ResultSetSPI // Specific iterator over ResultSetRows +{ + + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetColumn.java b/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetColumn.java new file mode 100644 index 0000000000..ec836ee7c9 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetColumn.java @@ -0,0 +1,56 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import org.alfresco.service.namespace.QName; + +/** + * The metadata for a column in a result set. + * All columns should have a data type, they may have a property type. + * + * @author andyh + * + */ +public interface ResultSetColumn +{ + /** + * The column name + * @return - the column name + */ + public String getName(); + + /** + * The type of the column + * @return - the data type for the column + */ + public QName getDataType(); + + /** + * The property definition if there is one for the column + * @return - the property definition or null if it does not make sense for the column + */ + public QName getPropertyType(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetMetaData.java b/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetMetaData.java new file mode 100644 index 0000000000..c4b57726a4 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetMetaData.java @@ -0,0 +1,111 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Meta Data associated with a result set. + * + * @author Andy Hind + */ +@AlfrescoPublicApi +public interface ResultSetMetaData +{ + + /** + * Return how, in fact, the result set was limited. + * This may not be how it was requested. + * + * If a limit of 100 were requested and there were 100 or less actual results + * this will report LimitBy.UNLIMITED. + * + * @return LimitBy + */ + public LimitBy getLimitedBy(); + + /** + * Return how permission evaluations are being made. + * + * @return PermissionEvaluationMode + */ + public PermissionEvaluationMode getPermissionEvaluationMode(); + + /** + * Get the parameters that were specified to define this search. + * + * @return SearchParameters + */ + public SearchParameters getSearchParameters(); + + /** + * Get the result set type + * @return ResultSetType + */ + public ResultSetType getResultSetType(); + + /** + * The selector meta-data. + * @return - the selector meta-data. + */ + public ResultSetSelector[] getSelectors(); + + + /** + * The column meta-data. + * @return - the column meta-data. + */ + public ResultSetColumn[] getColumns(); + + /** + * Get the names of the selectors. + * @return - the selector names. + */ + public String[] getSelectorNames(); + + /** + * Get the column names. + * @return - the names of the columns. + */ + public String[] getColumnNames(); + + /** + * Get the selector meta-data by name. + * @param name String + * @return - the selector meta-data. + */ + public ResultSetSelector getSelector(String name); + + /** + * Get the column meta-data by column name. + * @param name String + * @return - the column meta-data. + */ + public ResultSetColumn getColumn(String name); + + + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetRow.java b/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetRow.java new file mode 100644 index 0000000000..4f76cae815 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetRow.java @@ -0,0 +1,140 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; + +/** + * A row in a result set + * + * TODO: Support for other non attribute features such as parents and path + * + * @author andyh + * + */ +@AlfrescoPublicApi +public interface ResultSetRow +{ + /** + * Get the values of all available node properties. These are only properties + * that were stored in the query results and can vary depending on the query + * language that was used. + * + * @return Returns all the available node properties + */ + public Map getValues(); + + /** + * Get the data for a single column + * @param columnName String + * @return the value + */ + public Serializable getValue(String columnName); + + /** + * Get a node property value by name + * + * @param qname the property name + * @return Returns the node property for the given name + */ + public Serializable getValue(QName qname); + + /** + * The reference to the node that equates to this row in the result set + * + * @return Returns the reference to the node that makes this result + */ + public NodeRef getNodeRef(); + + + /** + * Gets the node refs + * @return a map of selector name to node ref + */ + public Map getNodeRefs(); + + + /** + * Gets the node ref related to the named selector + * @param selectorName String + * @return the node ref + */ + public NodeRef getNodeRef(String selectorName); + + /** + * Get the score for this row in the result set + * + * @return Returns the score for this row in the resultset + */ + public float getScore(); // Score is score + rank + potentially other + // stuff + + /** + * Get the scores . + * @return a map of selector name to score. + */ + public Map getScores(); + + /** + * Get the score related to the named selector. + * @param selectorName String + * @return - the score. + */ + public float getScore(String selectorName); + + + /** + * Get the containing result set + * + * @return Returns the containing resultset + */ + public ResultSet getResultSet(); + + /** + * @return Returns the name of the child association leading down to the + * node represented by this row + */ + public QName getQName(); + + /** + * Get the index of this result set in the result set + * If you want the overall position in paged reults you have to add the skipCount fo the result set. + * @return int + */ + public int getIndex(); + + /** + * @return Returns the child assoc ref for this row + */ + public ChildAssociationRef getChildAssocRef(); + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetSPI.java b/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetSPI.java new file mode 100644 index 0000000000..cbc149165b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetSPI.java @@ -0,0 +1,203 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.util.List; +import java.util.Map; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.util.Pair; + +/** + * This is the common interface for both row (Alfresco node) and column (CMIS style property or function) based results. + * The meta-data for the results sets contains the detailed info on what columns are available. For row based result + * sets there is no selector - all the nodes returned do not have to have a specific type or aspect. For example, an FTS + * search on properties of type d:content has no type constraint implied or otherwise. Searches against properties have + * an implied type, but as there can be more than one property -> more than one type or aspect implied (eg via OR in FTS + * or lucene) they are ignored An iterable result set from a searcher query. Implementations must implement the + * indexes for row lookup as zero-based. + * + * @author andyh + * @param + * @param + */ +@AlfrescoPublicApi +public interface ResultSetSPI extends Iterable // Specific iterator over ResultSetRows +{ + /** + * Get the number of rows in this result set. This will be less than or equal to the maximum number of rows + * requested or the full length of the results set if no restriction on length are specified. If a skip count is + * given, the length represents the number of results after the skip count and does not include the items skipped. + * + * @return the number of results. -1 means unknown and can be returned for lazy evaluations of permissions when the + * actual size is not known and evaluated upon request. + */ + public int length(); + + /** + * Attempt to get the number of rows that matched the query. This result set may only contain a section of the results. + * If a skip count is given the number found may or may not include the items skipped. + * This is best effort and only done if is cheap. + * For SOLR it is cheap; for the DB it may be expensive as permissions are done post query. + * If you want to know if there are more results to fetch use hasMore() + * @return long + */ + public long getNumberFound(); + + /** + * Get the id of the node at the given index (if there is only one selector or no selector) + * + * @param n + * zero-based index + * @return return the the node ref for the row if there is only one selector + */ + public NodeRef getNodeRef(int n); + + /** + * Get the score for the node at the given position (if there is only one selector or no selector) + * + * @param n + * zero-based index + * @return return the score for the row if there is only one selector + */ + public float getScore(int n); + + /** + * Close the result set and release any resources held/ The result set is bound to the transaction and will auto + * close at the end of the transaction. + */ + public void close(); + + /** + * Get a row from the result set by row index, starting at 0. + * + * @param i + * zero-based index + * @return return the row + */ + public ROW getRow(int i); + + /** + * Get a list of all the node refs in the result set (if there is only one selector or no selector) + * + * @return the node refs if there is only one selector or no selector * + */ + public List getNodeRefs(); + + /** + * Get a list of all the child associations in the results set. (if there is only one selectoror no selector) + * + * @return the child assoc refs if there is only one selector or no selector * + */ + public List getChildAssocRefs(); + + /** + * Get the child assoc ref for a particular row. (if there is only one selectoror no selector) + * + * @param n + * zero-based index + * @return the child assoc ref for the row if there is only one selector or no selector + */ + public ChildAssociationRef getChildAssocRef(int n); + + /** + * Get the meta data for the results set. + * + * @return the metadata + */ + public MD getResultSetMetaData(); + + /** + * Get the start point for this results set in the overall set of rows that match the query - this will be equal to + * the skip count set when executing the query, and zero if this is not set. + * + * @return the position of the first result in the overall result set + */ + public int getStart(); + + /** + * Was this result set curtailed - are there more pages to the result set? + * + * @return true if there are more pages in the result set + */ + public boolean hasMore(); + + /** + * Bulk fetch results in the cache + * + * @param bulkFetch boolean + */ + public boolean setBulkFetch(boolean bulkFetch); + + /** + * Do we bulk fetch + * + * @return - true if we do + */ + public boolean getBulkFetch(); + + /** + * Set the bulk fetch size + * + * @param bulkFetchSize int + */ + public int setBulkFetchSize(int bulkFetchSize); + + /** + * Get the bulk fetch size. + * + * @return the fetch size + */ + public int getBulkFetchSize(); + + /** + * @param field String + * @return List + */ + public List> getFieldFacet(String field); + + /** + * Gets the facet query results + * + * @return Map of {@literal } + */ + public Map getFacetQueries(); + + /** + * Gets the highlighting results. Returns a Map keyed by noderef. + * Each value is a pair of "fieldname" and a String array of highlight snippets + * @return the Map + */ + public Map>>> getHighlighting(); + /** + * Gets the spell check result + * + * @return SpellCheckResult + */ + public SpellCheckResult getSpellCheckResult(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetSelector.java b/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetSelector.java new file mode 100644 index 0000000000..42245e50b1 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetSelector.java @@ -0,0 +1,49 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import org.alfresco.service.namespace.QName; + +/** + * The metadata for a ResultSet selector. + * + * @author andyh + * + */ +public interface ResultSetSelector +{ + /** + * The unique name for the selector. + * @return - the unique name for the selector + */ + public String getName(); + + /** + * Get the Alfresco type QName for the type or aspect + * @return - the type or aspect + */ + public QName getType(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetType.java b/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetType.java new file mode 100644 index 0000000000..a9e793f0b1 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/ResultSetType.java @@ -0,0 +1,43 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +/** + * The two types of result set - column based and Node Ref based. + * @author andyh + * + */ +public enum ResultSetType +{ + /** + * Just the node ref is available for each row in the results. + */ + NODE_REF, + /** + * The node ref is available and a specified list of columns. + */ + COLUMN_AND_NODE_REF +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/SearchParameters.java b/data-model/src/main/java/org/alfresco/service/cmr/search/SearchParameters.java new file mode 100644 index 0000000000..edc776a204 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/SearchParameters.java @@ -0,0 +1,1646 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.search.MLAnalysisMode; +import org.alfresco.repo.search.impl.querymodel.QueryOptions; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.namespace.NamespaceService; +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * This class provides parameters to define a search. TODO - paging of results page number and page size - paging + * isolation - REPEATABLE READ, READ COMMITTED, may SEE ONCE tracking node refs in previous result sets - how long + * repeatable read may be held - limit by the number of permission evaluations + * + * @author Andy Hind + */ +@AlfrescoPublicApi +public class SearchParameters implements BasicSearchParameters +{ + /* + * The default limit if someone asks for a limited result set but does not say how to limit.... + */ + private static int DEFAULT_LIMIT = 500; + + /* + * Standard sort definitions for sorting in document and score order. + */ + /** + * Sort in the order docs were added to the index - oldest docs first + */ + public static final SortDefinition SORT_IN_DOCUMENT_ORDER_ASCENDING = new SortDefinition(SortDefinition.SortType.DOCUMENT, null, true); + + /** + * Sort in the reverse order docs were added to the index - new/updateed docs first + */ + public static final SortDefinition SORT_IN_DOCUMENT_ORDER_DESCENDING = new SortDefinition(SortDefinition.SortType.DOCUMENT, null, false); + + /** + * Sort in ascending score + */ + public static final SortDefinition SORT_IN_SCORE_ORDER_ASCENDING = new SortDefinition(SortDefinition.SortType.SCORE, null, true); + + /** + * Sort in descending score order + */ + public static final SortDefinition SORT_IN_SCORE_ORDER_DESCENDING = new SortDefinition(SortDefinition.SortType.SCORE, null, false); + + /** + * An emum defining if the default action is to "and" or "or" unspecified components in the query register. Not all + * search implementations will support this. + */ + public enum Operator + { + /** + * OR + */ + OR, + /** + * AND + */ + AND + } + + /* + * Expose as constants + */ + /** + * OR + */ + public static final Operator OR = Operator.OR; + + /** + * AND + */ + public static final Operator AND = Operator.AND; + + /** + * A parameter that can be passed to Solr to indicate an alternative dictionary should be used. + */ + public static final String ALTERNATIVE_DICTIONARY = "alternativeDic"; + + /* + * The parameters that can be set + */ + private String language; + + private String query; + + private ArrayList stores = new ArrayList(1); + + private ArrayList queryParameterDefinitions = new ArrayList(1); + + private boolean excludeDataInTheCurrentTransaction = false; + + private ArrayList sortDefinitions = new ArrayList(1); + + private ArrayList locales = new ArrayList(); + + private MLAnalysisMode mlAnalaysisMode = null; // Pick up from config if null + + private LimitBy limitBy = LimitBy.UNLIMITED; + + private PermissionEvaluationMode permissionEvaluation = PermissionEvaluationMode.EAGER; + + private int limit = DEFAULT_LIMIT; + + private HashSet allAttributes = new HashSet(); + + private HashSet textAttributes = new HashSet(); + + private int maxItems = -1; + + private int skipCount = 0; + + private Operator defaultFTSOperator = Operator.OR; + + private Operator defaultFTSFieldOperator = Operator.OR; + + private Map queryTemplates = new HashMap(); + + private String namespace = NamespaceService.CONTENT_MODEL_1_0_URI; + + // By default uses the central config + private int maxPermissionChecks = -1; + + // By default uses the central config + private long maxPermissionCheckTimeMillis = -1; + + private String defaultFieldName = "TEXT"; + + private ArrayList fieldFacets = new ArrayList(); + + private List facetQueries = new ArrayList(); + + private List filterQueries = new ArrayList(); + + private List> pivots = new ArrayList<>(); + + private Boolean useInMemorySort; + + private Integer maxRawResultSetSizeForInMemorySort; + + private Map extraParameters = new HashMap(); + + private boolean excludeTenantFilter = false; + + private boolean isBulkFetchEnabled = true; + + private QueryConsistency queryConsistency = QueryConsistency.DEFAULT; + + private Long sinceTxId; + + private String searchTerm; + + private boolean spellCheck; + + private GeneralHighlightParameters highlight; + + private IntervalParameters interval; + + private List stats; + + private List ranges; + + private boolean includeMetadata; + + private String timezone; + + /** + * Default constructor + */ + public SearchParameters() + { + super(); + } + + public SearchParameters copy() + { + SearchParameters sp = new SearchParameters(); + sp.allAttributes.addAll(this.allAttributes); + sp.defaultFieldName = this.defaultFieldName; + sp.defaultFTSFieldOperator = this.defaultFTSFieldOperator; + sp.defaultFTSOperator = this.defaultFTSOperator; + sp.excludeDataInTheCurrentTransaction = this.excludeDataInTheCurrentTransaction; + sp.fieldFacets.addAll(this.fieldFacets); + sp.language = this.language; + sp.limit = this.limit; + sp.limitBy = this.limitBy; + sp.locales.addAll(this.locales); + sp.maxItems = this.maxItems; + sp.maxPermissionChecks = this.maxPermissionChecks; + sp.maxPermissionCheckTimeMillis = this.maxPermissionCheckTimeMillis; + sp.mlAnalaysisMode = this.mlAnalaysisMode; + sp.namespace = this.namespace; + sp.permissionEvaluation = this.permissionEvaluation; + sp.query = this.query; + sp.queryParameterDefinitions.addAll(this.queryParameterDefinitions); + sp.queryTemplates.putAll(this.queryTemplates); + sp.skipCount = this.skipCount; + sp.sortDefinitions.addAll(this.sortDefinitions); + sp.stores.addAll(this.stores); + sp.textAttributes.addAll(this.textAttributes); + sp.useInMemorySort = this.useInMemorySort; + sp.maxRawResultSetSizeForInMemorySort = this.maxRawResultSetSizeForInMemorySort; + sp.isBulkFetchEnabled = this.isBulkFetchEnabled; + sp.excludeTenantFilter = this.excludeTenantFilter; + sp.queryConsistency = this.queryConsistency; + sp.sinceTxId = this.sinceTxId; + sp.facetQueries.addAll(this.facetQueries); + sp.filterQueries.addAll(this.filterQueries); + sp.pivots.addAll(this.pivots); + sp.searchTerm = this.searchTerm; + sp.spellCheck = this.spellCheck; + sp.highlight = this.highlight; + sp.interval = this.interval; + sp.stats = this.stats; + sp.ranges = this.ranges; + sp.timezone = this.timezone; + return sp; + } + + /** + * Construct from Query Options + * + * @param options QueryOptions + */ + public SearchParameters(QueryOptions options) + { + setSkipCount(options.getSkipCount()); + setMaxPermissionChecks(options.getMaxPermissionChecks()); + setMaxPermissionCheckTimeMillis(options.getMaxPermissionCheckTimeMillis()); + setBulkFetchEnabled(options.isBulkFetchEnabled()); + if (options.getMaxItems() >= 0) + { + setLimitBy(LimitBy.FINAL_SIZE); + setLimit(options.getMaxItems()); + setMaxItems(options.getMaxItems()); + } + else + { + setLimitBy(LimitBy.UNLIMITED); + } + } + + /** + * Get the search language + * + * @return - string id of search language + */ + public String getLanguage() + { + return language; + } + + /** + * Get the query. + * + * @return - the query string + */ + public String getQuery() + { + return query; + } + + /** + Sets parameters used for search highlighing + * @param highlight GeneralHighlightParameters + */ + public void setHighlight(GeneralHighlightParameters highlight) + { + this.highlight = highlight; + } + + public List getStats() + { + return stats; + } + + public void setStats(List stats) + { + this.stats = stats; + } + + public IntervalParameters getInterval() + { + return interval; + } + + /** + Sets parameters used for Intervals + * @param interval IntervalParameters + */ + public void setInterval(IntervalParameters interval) + { + this.interval = interval; + } + + public List getRanges() + { + return ranges; + } + + public void setRanges(List ranges) + { + this.ranges = ranges; + } + + /** + * Set the query language. + * + * @param language - + * the query language. + */ + public void setLanguage(String language) + { + this.language = language; + } + + public String getTimezone() + { + return timezone; + } + + /** + * Override the default TimeZone (UTC) + * @param timezone any zone ID supported by @see java.time.ZoneId + */ + public void setTimezone(String timezone) + { + this.timezone = timezone; + } + + public void addExtraParameter(String name, String value) + { + extraParameters.put(name, value); + } + + public Map getExtraParameters() + { + return extraParameters; + } + + /** + * Set the query string. + * + * @param query - + * the query string. + */ + public void setQuery(String query) + { + this.query = query; + } + + /** + * Set the stores to be supported - currently there can be only one. Searching across multiple stores is on the todo + * list. + * + * @param store StoreRef + */ + public void addStore(StoreRef store) + { + stores.add(store); + } + + /** + * Add parameter definitions for the query - used to parameterise the query string + * + * @param queryParameterDefinition QueryParameterDefinition + */ + public void addQueryParameterDefinition(QueryParameterDefinition queryParameterDefinition) + { + queryParameterDefinitions.add(queryParameterDefinition); + } + + /** + * If true, any data in the current transaction will be ignored in the search. You will not see anything you have + * added in the current transaction. By default you will see data in the current transaction. This effectively gives + * read committed isolation. There is a performance overhead for this, at least when using lucene. This flag may be + * set to avoid that performance hit if you know you do not want to find results that are yet to be committed (this + * includes creations, deletions and updates) + * + * @param excludeDataInTheCurrentTransaction boolean + */ + public void excludeDataInTheCurrentTransaction(boolean excludeDataInTheCurrentTransaction) + { + this.excludeDataInTheCurrentTransaction = excludeDataInTheCurrentTransaction; + } + + /** + * Add a sort to the query (for those query languages that do not support it directly) The first sort added is + * treated as primary, the second as secondary etc. A helper method to create SortDefinitions. + * + * @param field - + * this is initially a direct attribute on a node not an attribute on the parent etc TODO: It could be a + * relative path at some time. + * @param ascending - + * true to sort ascending, false for descending. + */ + public void addSort(String field, boolean ascending) + { + addSort(new SortDefinition(SortDefinition.SortType.FIELD, field, ascending)); + } + + /** + * Add a sort definition. + * + * @param sortDefinition - + * the sort definition to add. Use the static member variables for sorting in score and index order. + */ + public void addSort(SortDefinition sortDefinition) + { + sortDefinitions.add(sortDefinition); + } + + /** + * Gets the parameters used for search highlighing + * @return GeneralHighlightParameters - the highlighting parameters + */ + public GeneralHighlightParameters getHighlight() + { + return highlight; + } + + /** + * Is data in the current transaction excluded from the search. + * + * @return - true if data in the current transaction is ignored + */ + public boolean excludeDataInTheCurrentTransaction() + { + return excludeDataInTheCurrentTransaction; + } + + /** + * Get the query parameters that apply to this query. + * + * @return - the parameter + */ + public ArrayList getQueryParameterDefinitions() + { + return queryParameterDefinitions; + } + + /** + * Get the sort definitions that apply to this query. + * + * @return - the sort definitions + */ + public ArrayList getSortDefinitions() + { + return sortDefinitions; + } + + /** + * Get the stores in which this query should find results. + * + * @return - the list of stores + */ + public ArrayList getStores() + { + return stores; + } + + /** + * Set the default operator for query elements when they are not explicit in the query. + * + * @param defaultOperator Operator + */ + public void setDefaultOperator(Operator defaultOperator) + { + this.defaultFTSOperator = defaultOperator; + this.defaultFTSFieldOperator = defaultOperator; + } + + /** + * Get the default operator for query elements when they are not explicit in the query. + * + * @return the default operator + */ + public Operator getDefaultOperator() + { + return getDefaultFTSOperator(); + } + + /** + * Get how the result set should be limited + * + * @return how the result set will be or was limited + */ + public LimitBy getLimitBy() + { + return limitBy; + } + + /** + * Set how the result set should be limited. + * + * @param limitBy LimitBy + */ + public void setLimitBy(LimitBy limitBy) + { + this.limitBy = limitBy; + } + + /** + * Get when permissions are evaluated. + * + * @return - how permissions are evaluated + */ + public PermissionEvaluationMode getPermissionEvaluation() + { + return permissionEvaluation; + } + + /** + * Set when permissions are evaluated. + * + * @param permissionEvaluation PermissionEvaluationMode + */ + public void setPermissionEvaluation(PermissionEvaluationMode permissionEvaluation) + { + this.permissionEvaluation = permissionEvaluation; + } + + /** + * If limiting the result set in some way, get the limiting value used. + * + * @return the limit + */ + public int getLimit() + { + return limit; + } + + /** + * If limiting the result set in some way, set the limiting value used. + * + * @param limit int + */ + public void setLimit(int limit) + { + this.limit = limit; + } + + /** + * The way in which multilingual fields are treated durig a search. By default, only the specified locale is used + * and it must be an exact match. + * + * @return - how locale related text is tokenised + */ + public MLAnalysisMode getMlAnalaysisMode() + { + return mlAnalaysisMode; + } + + /** + * Set the way in which multilingual fields are treated durig a search. This controls in which locales an + * multilingual fields will match. + * + * @param mlAnalaysisMode MLAnalysisMode + */ + public void setMlAnalaysisMode(MLAnalysisMode mlAnalaysisMode) + { + this.mlAnalaysisMode = mlAnalaysisMode; + } + + /** + * Add a locale to include for multi-lingual text searches. If non are set, the default is to use the user's locale. + * + * @param locale Locale + */ + public void addLocale(Locale locale) + { + locales.add(locale); + } + + /** + * Get the locales used for multi-lingual text searches. + * + * @return - the locales + */ + public List getLocales() + { + return Collections.unmodifiableList(locales); + } + + /** + * Add a field for TEXT expansion + * + * @param attribute - + * field/attribute in the index + */ + public void addTextAttribute(String attribute) + { + textAttributes.add(attribute); + } + + /** + * Get the text attributes used for text expansion. + * + * @return the text attributes used for text expansion + */ + public Set getTextAttributes() + { + return Collections.unmodifiableSet(textAttributes); + } + + /** + * Add a field for ALL expansion + * + * @param attribute - + * field/attribute in the index + */ + public void addAllAttribute(String attribute) + { + allAttributes.add(attribute); + } + + /** + * Get the text attributes used for ALL expansion. + * + * @return the text attributes used for ALL expansion + */ + public Set getAllAttributes() + { + return Collections.unmodifiableSet(allAttributes); + } + + /** + * Get the max number of rows for the result set 0 or less is unlimited + * + * @return the maxItems + */ + public int getMaxItems() + { + return maxItems; + } + + /** + * Set the max number of rows for the result set. + * A negative value implies unlimited + * 0 will return no results. + * + * @param maxItems + * the maxItems to set + */ + public void setMaxItems(int maxItems) + { + this.maxItems = maxItems; + } + + /** + * Get the skip count - the number of rows to skip at the start of the query. + * + * @return the skipCount + */ + public int getSkipCount() + { + return skipCount; + } + + /** + * Set the skip count - the number of rows to skip at the start of the query. + * + * @param skipCount + * the skipCount to set + */ + public void setSkipCount(int skipCount) + { + this.skipCount = skipCount; + } + + /** + * Get the default connective used when OR and AND are not specified for the FTS contains() function. + * + * @return the defaultFTSConnective + */ + public Operator getDefaultFTSOperator() + { + return defaultFTSOperator; + } + + /** + * Set the default connective used when OR and AND are not specified for the FTS contains() function. + * + * @param defaultFTSOperator + * the defaultFTSOperator to set + */ + public void setDefaultFTSOperator(Operator defaultFTSOperator) + { + this.defaultFTSOperator = defaultFTSOperator; + } + + /** + * As getDefaultFTSConnective() but for field groups + * + * @return the defaultFTSFieldConnective + */ + public Operator getDefaultFTSFieldOperator() + { + return defaultFTSFieldOperator; + } + + /** + * As setDefaultFTSConnective() but for field groups + * + * @param defaultFTSFieldOperator + * the defaultFTSFieldOperator to set + */ + public void setDefaultFTSFieldConnective(Operator defaultFTSFieldOperator) + { + this.defaultFTSFieldOperator = defaultFTSFieldOperator; + } + + /** + * Get the default namespace. + * + * @return the default namspace uri or prefix. + */ + public String getNamespace() + { + return namespace; + } + + /** + * Set the default namespace + * + * @param namespace - + * the uri or prefix for the default namespace. + */ + public void setNamespace(String namespace) + { + this.namespace = namespace; + } + + /** + * Get the query templates + * + * @return - the query templates + */ + public Map getQueryTemplates() + { + return queryTemplates; + } + + /** + * Add/replace a query template Not all languages support query templates + * + * @param name String + * @param template String + * @return any removed template or null + */ + public String addQueryTemplate(String name, String template) + { + return queryTemplates.put(name, template); + } + + public long getMaxPermissionCheckTimeMillis() + { + return maxPermissionCheckTimeMillis; + } + + public void setMaxPermissionCheckTimeMillis(long maxPermissionCheckTimeMillis) + { + this.maxPermissionCheckTimeMillis = maxPermissionCheckTimeMillis; + } + + public int getMaxPermissionChecks() + { + return maxPermissionChecks; + } + + public void setMaxPermissionChecks(int maxPermissionChecks) + { + this.maxPermissionChecks = maxPermissionChecks; + } + + /** + * @return the useInMemorySort + */ + public Boolean getUseInMemorySort() + { + return useInMemorySort; + } + + /** + * @param useInMemorySort the useInMemorySort to set + */ + public void setUseInMemorySort(Boolean useInMemorySort) + { + this.useInMemorySort = useInMemorySort; + } + + /** + * @return the maxRawResultSetSizeForInMemorySort + */ + public Integer getMaxRawResultSetSizeForInMemorySort() + { + return maxRawResultSetSizeForInMemorySort; + } + + /** + * @param maxRawResultSetSizeForInMemorySort the maxRawResultSetSizeForInMemorySort to set + */ + public void setMaxRawResultSetSizeForInMemorySort(Integer maxRawResultSetSizeForInMemorySort) + { + this.maxRawResultSetSizeForInMemorySort = maxRawResultSetSizeForInMemorySort; + } + + /** + * @return true if bulk fetch is enabled + */ + public boolean isBulkFetchEnabled() + { + return isBulkFetchEnabled; + } + + /** + * @param isBulkFetchEnabled boolean + */ + public void setBulkFetchEnabled(boolean isBulkFetchEnabled) + { + this.isBulkFetchEnabled = isBulkFetchEnabled; + } + + + /** + * A helper class for sort definition. Encapsulated using the lucene sortType, field name and a flag for + * ascending/descending. + * + * @author Andy Hind + */ + public static class SortDefinition + { + + /** + * What is used for the sort + * + * @author andyh + */ + public enum SortType + { + /** + * A Field + */ + FIELD, + /** + * Doc number + */ + DOCUMENT, + /** + * Score + */ + SCORE + }; + + SortType sortType; + + String field; + + boolean ascending; + + public SortDefinition(SortType sortType, String field, boolean ascending) + { + this.sortType = sortType; + this.field = field; + this.ascending = ascending; + } + + /** + * Is ascending + * + * @return true if ascending + */ + public boolean isAscending() + { + return ascending; + } + + /** + * Field + * + * @return - the field + */ + public String getField() + { + return field; + } + + /** + * What is used for the sort + * + * @return sort type + */ + public SortType getSortType() + { + return sortType; + } + + } + + /** + * @return the default field name + */ + public String getDefaultFieldName() + { + return defaultFieldName; + } + + /** + * @param defaultFieldName - the default field name to use + */ + public void setDefaultFieldName(String defaultFieldName) + { + this.defaultFieldName = defaultFieldName; + } + + public List getFieldFacets() + { + return fieldFacets; + } + + public void addFieldFacet(FieldFacet fieldFacet) + { + fieldFacets.add(fieldFacet); + } + + public List getFacetQueries() + { + return facetQueries; + } + + public void addFacetQuery(String facetQuery) + { + facetQueries.add(facetQuery); + } + + public List getFilterQueries() + { + return filterQueries; + } + + public void addFilterQuery(String filterQuery) + { + filterQueries.add(filterQuery); + } + + public List> getPivots() + { + return pivots; + } + + public void addPivots(List pivotFields) + { + pivots.add(pivotFields); + } + + public Locale getSortLocale() + { + List locales = getLocales(); + if (((locales == null) || (locales.size() == 0))) + { + locales = Collections.singletonList(I18NUtil.getLocale()); + } + + if (locales.size() > 1) + { + throw new AlfrescoRuntimeException("Order on text/mltext properties with more than one locale is not curently supported"); + } + + Locale sortLocale = locales.get(0); + return sortLocale; + } + + public void setExcludeTenantFilter(boolean excludeTenantFilter) + { + this.excludeTenantFilter = excludeTenantFilter; + } + + /** + * + */ + public boolean getExcludeTenantFilter() + { + return excludeTenantFilter; + } + + public void setQueryConsistency(QueryConsistency queryConsistency) + { + this.queryConsistency = queryConsistency; + } + + /** + * @return the queryConsistency + */ + public QueryConsistency getQueryConsistency() + { + return queryConsistency; + } + + + /** + * If not null, then the search should only include results from transactions after {@code sinceTxId}. + * @return sinceTxId + */ + public Long getSinceTxId() + { + return this.sinceTxId; + } + + /** + * If not null, then the search should only include results from transactions after {@code sinceTxId}. + * @param sinceTxId Long + */ + public void setSinceTxId(Long sinceTxId) + { + this.sinceTxId = sinceTxId; + } + + /** + * @return the searchTerm + */ + public String getSearchTerm() + { + if((searchTerm == null) || (searchTerm.length() == 0)) + { + return getQuery(); + } + else + { + return this.searchTerm; + } + } + + /** + * @param searchTerm the searchTerm to set + */ + public void setSearchTerm(String searchTerm) + { + this.searchTerm = searchTerm; + } + + /** + * @return the spellCheck + */ + public boolean isSpellCheck() + { + return this.spellCheck; + } + + /** + * Checks if faceting is used as part of the query, Search-347. + * @param searchParameters + * @return true if exists + */ + public boolean hasFaceting() + { + if(facetQueries != null && !facetQueries.isEmpty()) + { + return true; + } + if(fieldFacets != null && !fieldFacets.isEmpty()) + { + return true; + } + if(interval != null) + { + return true; + } + if(pivots != null && !pivots.isEmpty()) + { + return true; + } + if(ranges != null) + { + return true; + } + if(stats != null && !stats.isEmpty()) + { + return true; + } + return false; + } + + /** + * @param spellCheck the spellCheck to set + */ + public void setSpellCheck(boolean spellCheck) + { + this.spellCheck = spellCheck; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((allAttributes == null) ? 0 : allAttributes.hashCode()); + result = prime * result + ((defaultFTSFieldOperator == null) ? 0 : defaultFTSFieldOperator.hashCode()); + result = prime * result + ((defaultFTSOperator == null) ? 0 : defaultFTSOperator.hashCode()); + result = prime * result + ((defaultFieldName == null) ? 0 : defaultFieldName.hashCode()); + result = prime * result + (excludeDataInTheCurrentTransaction ? 1231 : 1237); + result = prime * result + (excludeTenantFilter ? 1231 : 1237); + result = prime * result + ((fieldFacets == null) ? 0 : fieldFacets.hashCode()); + result = prime * result + ((language == null) ? 0 : language.hashCode()); + result = prime * result + limit; + result = prime * result + ((limitBy == null) ? 0 : limitBy.hashCode()); + result = prime * result + ((locales == null) ? 0 : locales.hashCode()); + result = prime * result + maxItems; + result = prime * result + (int) (maxPermissionCheckTimeMillis ^ (maxPermissionCheckTimeMillis >>> 32)); + result = prime * result + maxPermissionChecks; + result = prime * result + ((maxRawResultSetSizeForInMemorySort == null) ? 0 : maxRawResultSetSizeForInMemorySort.hashCode()); + result = prime * result + ((mlAnalaysisMode == null) ? 0 : mlAnalaysisMode.hashCode()); + result = prime * result + ((namespace == null) ? 0 : namespace.hashCode()); + result = prime * result + ((permissionEvaluation == null) ? 0 : permissionEvaluation.hashCode()); + result = prime * result + ((query == null) ? 0 : query.hashCode()); + result = prime * result + ((queryConsistency == null) ? 0 : queryConsistency.hashCode()); + result = prime * result + ((queryParameterDefinitions == null) ? 0 : queryParameterDefinitions.hashCode()); + result = prime * result + ((queryTemplates == null) ? 0 : queryTemplates.hashCode()); + result = prime * result + skipCount; + result = prime * result + ((sortDefinitions == null) ? 0 : sortDefinitions.hashCode()); + result = prime * result + ((stores == null) ? 0 : stores.hashCode()); + result = prime * result + ((textAttributes == null) ? 0 : textAttributes.hashCode()); + result = prime * result + ((useInMemorySort == null) ? 0 : useInMemorySort.hashCode()); + result = prime * result + ((sinceTxId == null) ? 0 : sinceTxId.hashCode()); + result = prime * result + ((facetQueries.isEmpty()) ? 0 : facetQueries.hashCode()); + result = prime * result + ((filterQueries.isEmpty()) ? 0 : filterQueries.hashCode()); + result = prime * result + ((pivots.isEmpty()) ? 0 : pivots.hashCode()); + result = prime * result + ((ranges == null) ? 0 : ranges.hashCode()); + result = prime * result + ((searchTerm == null) ? 0 : searchTerm.hashCode()); + result = prime * result + (spellCheck ? 1231 : 1237); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SearchParameters other = (SearchParameters) obj; + if (allAttributes == null) + { + if (other.allAttributes != null) + return false; + } + else if (!allAttributes.equals(other.allAttributes)) + return false; + if (defaultFTSFieldOperator != other.defaultFTSFieldOperator) + return false; + if (defaultFTSOperator != other.defaultFTSOperator) + return false; + if (defaultFieldName == null) + { + if (other.defaultFieldName != null) + return false; + } + else if (!defaultFieldName.equals(other.defaultFieldName)) + return false; + if (excludeDataInTheCurrentTransaction != other.excludeDataInTheCurrentTransaction) + return false; + if (excludeTenantFilter != other.excludeTenantFilter) + return false; + if (fieldFacets == null) + { + if (other.fieldFacets != null) + return false; + } + else if (!fieldFacets.equals(other.fieldFacets)) + return false; + if (language == null) + { + if (other.language != null) + return false; + } + else if (!language.equals(other.language)) + return false; + if (limit != other.limit) + return false; + if (limitBy != other.limitBy) + return false; + if (locales == null) + { + if (other.locales != null) + return false; + } + else if (!locales.equals(other.locales)) + return false; + if (maxItems != other.maxItems) + return false; + if (maxPermissionCheckTimeMillis != other.maxPermissionCheckTimeMillis) + return false; + if (maxPermissionChecks != other.maxPermissionChecks) + return false; + if (maxRawResultSetSizeForInMemorySort == null) + { + if (other.maxRawResultSetSizeForInMemorySort != null) + return false; + } + else if (!maxRawResultSetSizeForInMemorySort.equals(other.maxRawResultSetSizeForInMemorySort)) + return false; + if (mlAnalaysisMode != other.mlAnalaysisMode) + return false; + if (namespace == null) + { + if (other.namespace != null) + return false; + } + else if (!namespace.equals(other.namespace)) + return false; + if (permissionEvaluation != other.permissionEvaluation) + return false; + if (query == null) + { + if (other.query != null) + return false; + } + else if (!query.equals(other.query)) + return false; + if (queryConsistency != other.queryConsistency) + return false; + if (queryParameterDefinitions == null) + { + if (other.queryParameterDefinitions != null) + return false; + } + else if (!queryParameterDefinitions.equals(other.queryParameterDefinitions)) + return false; + if (queryTemplates == null) + { + if (other.queryTemplates != null) + return false; + } + else if (!queryTemplates.equals(other.queryTemplates)) + return false; + if (skipCount != other.skipCount) + return false; + if (sortDefinitions == null) + { + if (other.sortDefinitions != null) + return false; + } + else if (!sortDefinitions.equals(other.sortDefinitions)) + return false; + if (stores == null) + { + if (other.stores != null) + return false; + } + else if (!stores.equals(other.stores)) + return false; + if (textAttributes == null) + { + if (other.textAttributes != null) + return false; + } + else if (!textAttributes.equals(other.textAttributes)) + return false; + if (useInMemorySort == null) + { + if (other.useInMemorySort != null) + return false; + } + else if (!useInMemorySort.equals(other.useInMemorySort)) + return false; + if (sinceTxId == null) + { + if (other.sinceTxId != null) + return false; + } + else if (!sinceTxId.equals(other.sinceTxId)) + return false; + if (!facetQueries.equals(other.facetQueries)) + return false; + if (!filterQueries.equals(other.filterQueries)) + return false; + if (!pivots.equals(other.pivots)) + return false; + if (searchTerm == null) + { + if (other.searchTerm != null) + return false; + } + else if (!searchTerm.equals(other.searchTerm)) + return false; + if (spellCheck != other.spellCheck) + return false; + return true; + } + + + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() + { + // used for debug logging + StringBuilder builder = new StringBuilder(1000); + builder.append("SearchParameters [language=").append(this.language).append(", query=").append(this.query) + .append(", stores=").append(this.stores).append(", queryParameterDefinitions=") + .append(this.queryParameterDefinitions).append(", excludeDataInTheCurrentTransaction=") + .append(this.excludeDataInTheCurrentTransaction).append(", sortDefinitions=") + .append(this.sortDefinitions).append(", locales=").append(this.locales) + .append(", mlAnalaysisMode=").append(this.mlAnalaysisMode).append(", limitBy=") + .append(this.limitBy).append(", permissionEvaluation=").append(this.permissionEvaluation) + .append(", limit=").append(this.limit).append(", allAttributes=").append(this.allAttributes) + .append(", textAttributes=").append(this.textAttributes).append(", maxItems=") + .append(this.maxItems).append(", skipCount=").append(this.skipCount) + .append(", defaultFTSOperator=").append(this.defaultFTSOperator) + .append(", defaultFTSFieldOperator=").append(this.defaultFTSFieldOperator) + .append(", queryTemplates=").append(this.queryTemplates).append(", namespace=") + .append(this.namespace).append(", maxPermissionChecks=").append(this.maxPermissionChecks) + .append(", maxPermissionCheckTimeMillis=").append(this.maxPermissionCheckTimeMillis) + .append(", defaultFieldName=").append(this.defaultFieldName) + .append(", fieldFacets=").append(this.fieldFacets) + .append(", facetQueries=").append(this.facetQueries) + .append(", filterQueries=").append(this.filterQueries) + .append(", pivots=").append(this.pivots) + .append(", stats=").append(this.stats) + .append(", useInMemorySort=").append(this.useInMemorySort) + .append(", maxRawResultSetSizeForInMemorySort=").append(this.maxRawResultSetSizeForInMemorySort) + .append(", extraParameters=").append(this.extraParameters).append(", excludeTenantFilter=") + .append(this.excludeTenantFilter).append(", isBulkFetchEnabled=").append(this.isBulkFetchEnabled) + .append(", queryConsistency=").append(this.queryConsistency).append(", sinceTxId=") + .append(this.sinceTxId).append(", searchTerm=").append(this.searchTerm) + .append(", highlight=").append(this.highlight) + .append(", interval=").append(this.interval) + .append(", range=").append(this.ranges) + .append(", timezone=").append(this.timezone) + .append(", spellCheck=").append(this.spellCheck).append("]"); + return builder.toString(); + } + + public String toAuditString() + { + // used for repository audit (note: will trimmed if it exceeds 1024 chars) + StringBuilder builder = new StringBuilder(1000); + builder.append("{lang=").append(this.language) + .append(", query=").append(this.query) + .append(", stores=").append(this.stores) + .append(", defaultFTSOp=").append(this.defaultFTSOperator) + .append(", defaultFTSFieldOp=").append(this.defaultFTSFieldOperator); + + if ((queryTemplates != null) && (! queryTemplates.isEmpty())) + { + builder.append(", queryTemplates=").append(this.queryTemplates); + } + + if ((filterQueries != null) && (! filterQueries.isEmpty())) + { + builder.append(", filterQueries=").append(this.filterQueries); + } + + if ((searchTerm != null) && (! searchTerm.isEmpty())) + { + builder.append(", searchTerm=").append(this.searchTerm); + } + + builder.append("}"); + + return builder.toString(); + } + + + public enum FieldFacetSort + { + COUNT, INDEX; + } + + public enum FieldFacetMethod + { + ENUM, FC; + } + + public static class FieldFacet + { + String field; + String label; + List excludeFilters; + String prefix = null; + FieldFacetSort sort = null; + Integer limitOrNull = null; + int offset = 0; + int minCount = 0; + boolean countDocsMissingFacetField = false; + FieldFacetMethod method = null; + int enumMethodCacheMinDF = 0; + + public FieldFacet(String field) + { + this.field = field; + } + + public String getField() + { + return field; + } + + public void setField(String field) + { + this.field = field; + } + + public String getPrefix() + { + return prefix; + } + + public void setPrefix(String prefix) + { + this.prefix = prefix; + } + + public FieldFacetSort getSort() + { + return sort; + } + + public void setSort(FieldFacetSort sort) + { + this.sort = sort; + } + + @Deprecated + /** + * Will return 100 as the old default but this is now defined in configuration and will be wrong if no explicitly set + * + * @return + */ + public int getLimit() + { + return limitOrNull == null ? 100 : limitOrNull.intValue(); + } + + @Deprecated + public void setLimit(int limit) + { + this.limitOrNull = limit; + } + + public void setLimitOrNull(Integer limitOrNull) + { + this.limitOrNull = limitOrNull; + } + + + public Integer getLimitOrNull() + { + return limitOrNull; + } + + public int getOffset() + { + return offset; + } + + public void setOffset(int offset) + { + this.offset = offset; + } + + public int getMinCount() + { + return minCount; + } + + public void setMinCount(int minCount) + { + this.minCount = minCount; + } + + public boolean isCountDocsMissingFacetField() + { + return countDocsMissingFacetField; + } + + public void setCountDocsMissingFacetField(boolean countDocsMissingFacetField) + { + this.countDocsMissingFacetField = countDocsMissingFacetField; + } + + public FieldFacetMethod getMethod() + { + return method; + } + + public void setMethod(FieldFacetMethod method) + { + this.method = method; + } + + public int getEnumMethodCacheMinDF() + { + return enumMethodCacheMinDF; + } + + public void setEnumMethodCacheMinDF(int enumMethodCacheMinDF) + { + this.enumMethodCacheMinDF = enumMethodCacheMinDF; + } + + public String getLabel() + { + return label; + } + + public void setLabel(String label) + { + this.label = label; + } + + public List getExcludeFilters() + { + return excludeFilters; + } + + public void setExcludeFilters(List excludeFilters) + { + this.excludeFilters = excludeFilters; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + FieldFacet that = (FieldFacet) o; + + if (offset != that.offset) + return false; + if (minCount != that.minCount) + return false; + if (countDocsMissingFacetField != that.countDocsMissingFacetField) + return false; + if (enumMethodCacheMinDF != that.enumMethodCacheMinDF) + return false; + if (!field.equals(that.field)) + return false; + if (label != null ? !label.equals(that.label) : that.label != null) + return false; + if (excludeFilters != null ? !excludeFilters.equals(that.excludeFilters) : that.excludeFilters != null) + return false; + if (prefix != null ? !prefix.equals(that.prefix) : that.prefix != null) + return false; + if (sort != that.sort) + return false; + if (limitOrNull != null ? !limitOrNull.equals(that.limitOrNull) : that.limitOrNull != null) + return false; + if (method != that.method) + return false; + + return true; + } + + @Override + public int hashCode() + { + int result = field.hashCode(); + result = 31 * result + (label != null ? label.hashCode() : 0); + result = 31 * result + (excludeFilters != null ? excludeFilters.hashCode() : 0); + result = 31 * result + (prefix != null ? prefix.hashCode() : 0); + result = 31 * result + (sort != null ? sort.hashCode() : 0); + result = 31 * result + (limitOrNull != null ? limitOrNull.hashCode() : 0); + result = 31 * result + offset; + result = 31 * result + minCount; + result = 31 * result + (countDocsMissingFacetField ? 1 : 0); + result = 31 * result + (method != null ? method.hashCode() : 0); + result = 31 * result + enumMethodCacheMinDF; + return result; + } + } + + /** + * @param length int + * @param useInMemorySortDefault boolean + * @param maxRawResultSetSizeForInMemorySortDefault int + * @return boolean + */ + public boolean usePostSort(int length, boolean useInMemorySortDefault, int maxRawResultSetSizeForInMemorySortDefault) + { + boolean use = (useInMemorySort == null) ? useInMemorySortDefault : useInMemorySort.booleanValue(); + int max = (maxRawResultSetSizeForInMemorySort == null) ? maxRawResultSetSizeForInMemorySortDefault : maxRawResultSetSizeForInMemorySort.intValue(); + return use && (length <= max); + } + + public boolean isIncludeMetadata() + { + return includeMetadata; + } + + public void setIncludeMetadata(boolean includeMetadata) + { + this.includeMetadata = includeMetadata; + } + + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/SearchSQLParameters.java b/data-model/src/main/java/org/alfresco/service/cmr/search/SearchSQLParameters.java new file mode 100644 index 0000000000..b4e5e10d66 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/SearchSQLParameters.java @@ -0,0 +1,111 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.SearchParameters.SortDefinition; + +/** + * This class provides the search parameters to construct a search query. + * @author Michael Suzuki + * + */ +public class SearchSQLParameters implements BasicSearchParameters +{ + private final String language; + private final String query; + private List stores = new ArrayList<>(); + private List locales = new ArrayList<>(); + private boolean includeMetadata; + + public SearchSQLParameters(String query, String language, List locales, boolean includeMetadata) + { + this.query = query; + this.language = language; + this.locales = locales; + this.includeMetadata = includeMetadata; + } + + @Override + public String getLanguage() + { + return language; + } + + @Override + public String getQuery() + { + return query; + } + + @Override + public List getStores() + { + return stores; + } + + @Override + public List getLocales() + { + return locales; + } + + @Override + public List getSortDefinitions() + { + return null; + } + /** + * Set the stores to be supported - currently there can be only one. Searching across multiple stores is on the todo + * list. + * + * @param store StoreRef + */ + public void addStore(StoreRef store) + { + stores.add(store); + } + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("SearchParameters [language=").append(this.language) + .append(", query=").append(this.query).append(", stores=").append(this.stores) + .append(", locales=").append(this.locales).append("]"); + return builder.toString(); + + } + + public boolean isIncludeMetadata() + { + return includeMetadata; + } + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/SearchService.java b/data-model/src/main/java/org/alfresco/service/cmr/search/SearchService.java new file mode 100644 index 0000000000..a15ec16e02 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/SearchService.java @@ -0,0 +1,275 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.io.Serializable; +import java.util.List; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.Auditable; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.repository.XPathException; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; + +/** + * This encapsulates the execution of search against different indexing + * mechanisms. + * + * Canned queries have been translated into the query string by this stage. + * Handling of parameterisation is left to the implementation. + * + * @author Andy hind + * + */ +@AlfrescoPublicApi +public interface SearchService +{ + public static final String LANGUAGE_LUCENE = "lucene"; + + public static final String LANGUAGE_XPATH = "xpath"; + + public static final String LANGUAGE_FTS_ALFRESCO = "fts-alfresco"; + + public static final String LANGUAGE_SOLR_FTS_ALFRESCO = "solr-fts-alfresco"; + + public static final String LANGUAGE_CMIS_STRICT = "cmis-strict"; + + public static final String LANGUAGE_CMIS_ALFRESCO = "cmis-alfresco"; + + public static final String LANGUAGE_SOLR_CMIS = "solr-cmis"; + + public static final String LANGUAGE_SOLR_ALFRESCO = "solr-alfresco"; + + public static final String LANGUAGE_SOLR_SQL = "solr-sql"; + + /** + * Search against a store. Pulls back all attributes on each node. Does not + * allow parameterisation. + * + * @param store - + * the store against which to search + * @param language - + * the query language + * @param query - + * the query string - which may include parameters + * @return Returns the query results + */ + @Auditable(parameters = {"store", "language", "query"}) + public ResultSet query(StoreRef store, String language, String query); + + /** + * Search against a store. + * + * @param store - + * the store against which to search + * @param language - + * the query language + * @param query - + * the query string - which may include parameters + * @param queryParameterDefinitions - + * query parameter definitions - the default value is used for + * the value. + * @return Returns the query results + */ + @Auditable(parameters = {"store", "language", "query", "queryParameterDefinitions"}) + public ResultSet query(StoreRef store, String language, String query, + QueryParameterDefinition[] queryParameterDefinitions); + + + /** + * Execute a canned query + * + * @param store - + * the store against which to search + * @param queryId - + * the query identifier + * @param queryParameters - + * parameterisation for the canned query + * @return Returns the query results + */ + @Auditable(parameters = {"store", "queryId", "queryParameters"}) + public ResultSet query(StoreRef store, QName queryId, QueryParameter[] queryParameters); + + /** + * Search using the given SearchParameters + */ + + @Auditable(parameters = {"searchParameters"}) + public ResultSet query(SearchParameters searchParameters); + + /** + * Select nodes using an xpath expression. + * + * @param contextNodeRef - + * the context node for relative expressions etc + * @param xpath - + * the xpath string to evaluate + * @param parameters - + * parameters to bind in to the xpath expression, may be null for no parameters + * @param namespacePrefixResolver - + * prefix to namespace mappings + * @param followAllParentLinks - + * if false ".." follows only the primary parent links, if true + * it follows all + * @return a list of the node refs of the selected nodes + */ + @Auditable( + + parameters = {"contextNodeRef", "xpath", "parameters", "namespacePrefixResolver", "followAllParentLinks"}, + recordable = {true, true, true, false, true}) + public List selectNodes(NodeRef contextNodeRef, String xpath, QueryParameterDefinition[] parameters, + NamespacePrefixResolver namespacePrefixResolver, boolean followAllParentLinks) + throws InvalidNodeRefException, XPathException; + + /** + * Select nodes using an xpath expression. + * + * @param contextNodeRef - + * the context node for relative expressions etc + * @param xpath - + * the xpath string to evaluate + * @param parameters - + * parameters to bind in to the xpath expression, may be null for no parameters + * @param namespacePrefixResolver - + * prefix to namespace mappings + * @param followAllParentLinks - + * if false ".." follows only the primary parent links, if true + * it follows all + * @param language - + * the xpath variant + * @return a list of all the node refs of the selected nodes + */ + @Auditable( + + parameters = {"contextNodeRef", "xpath", "parameters", "namespacePrefixResolver", "followAllParentLinks", "language"}, + recordable = {true, true, true, false, true, true}) + public List selectNodes(NodeRef contextNodeRef, String xpath, QueryParameterDefinition[] parameters, + NamespacePrefixResolver namespacePrefixResolver, boolean followAllParentLinks, String language) + throws InvalidNodeRefException, XPathException; + + /** + * Select properties using an xpath expression + * + * @param contextNodeRef - + * the context node for relative expressions etc + * @param xpath - + * the xpath string to evaluate + * @param parameters - + * parameters to bind in to the xpath expression + * @param namespacePrefixResolver - + * prefix to namespace mappings + * @param followAllParentLinks - + * if false ".." follows only the primary parent links, if true + * it follows all + * @return a list of property values + */ + @Auditable( + + parameters = {"contextNodeRef", "xpath", "parameters", "namespacePrefixResolver", "followAllParentLinks"}, + recordable = {true, true, true, false, true}) + public List selectProperties(NodeRef contextNodeRef, String xpath, + QueryParameterDefinition[] parameters, NamespacePrefixResolver namespacePrefixResolver, + boolean followAllParentLinks) throws InvalidNodeRefException, XPathException; + + /** + * Select properties using an xpath expression + * + * @param contextNodeRef - + * the context node for relative expressions etc + * @param xpath - + * the xpath string to evaluate + * @param parameters - + * parameters to bind in to the xpath expression + * @param namespacePrefixResolver - + * prefix to namespace mappings + * @param followAllParentLinks - + * if false ".." follows only the primary parent links, if true + * it follows all + * @param language - + * the xpath variant + * @return a list of property values + */ + @Auditable( + + parameters = {"contextNodeRef", "xpath", "parameters", "namespacePrefixResolver", "followAllParentLinks", "language"}, + recordable = {true, true, true, false, true, true}) + public List selectProperties(NodeRef contextNodeRef, String xpath, + QueryParameterDefinition[] parameters, NamespacePrefixResolver namespacePrefixResolver, + boolean followAllParentLinks, String language) throws InvalidNodeRefException, XPathException; + + /** + * Search for string pattern in both the node text (if present) and node + * properties + * + * @param nodeRef + * the node to get + * @param propertyQName + * the name of the property + * @param googleLikePattern + * a Google-like pattern to search for in the property value + * @return Returns true if the pattern could be found - uses the default OR operator + */ + @Auditable(parameters = {"nodeRef", "propertyQName", "googleLikePattern"}) + public boolean contains(NodeRef nodeRef, QName propertyQName, String googleLikePattern) + throws InvalidNodeRefException; + + /** + * Search for string pattern in both the node text (if present) and node + * properties + * + * @param nodeRef + * the node to get + * @param propertyQName + * the name of the property + * @param googleLikePattern + * a Google-like pattern to search for in the property value + * @return Returns true if the pattern could be found + */ + @Auditable(parameters = {"nodeRef", "propertyQName", "googleLikePattern", "defaultOperator"}) + public boolean contains(NodeRef nodeRef, QName propertyQName, String googleLikePattern, SearchParameters.Operator defaultOperator) + throws InvalidNodeRefException; + + /** + * Search for string pattern in both the node text (if present) and node + * properties + * + * @param nodeRef + * the node to get + * @param propertyQName + * the name of the property (mandatory) + * @param sqlLikePattern + * a SQL-like pattern to search for + * @param includeFTS - + * include full text search matches in the like test + * @return Returns true if the pattern could be found + */ + @Auditable(parameters = {"nodeRef", "propertyQName", "sqlLikePattern", "includeFTS"}) + public boolean like(NodeRef nodeRef, QName propertyQName, String sqlLikePattern, boolean includeFTS) + throws InvalidNodeRefException; +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/SpellCheckResult.java b/data-model/src/main/java/org/alfresco/service/cmr/search/SpellCheckResult.java new file mode 100644 index 0000000000..ee05ec9d15 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/SpellCheckResult.java @@ -0,0 +1,84 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.service.cmr.search; + +import java.io.Serializable; +import java.util.List; + +/** + * @author Jamal Kaabi-Mofrad + * @since 5.0 + */ +public class SpellCheckResult implements Serializable +{ + private static final long serialVersionUID = -4270859221984496771L; + + private final String resultName; + private final List results; + private final boolean searchedFor; + private final boolean spellCheckExist; + + public SpellCheckResult(String resultName, List results, boolean searchedFor) + { + this.resultName = resultName; + this.results = results; + this.searchedFor = searchedFor; + this.spellCheckExist = (resultName == null) ? false : true; + } + + /** + * @return the resultName + */ + public String getResultName() + { + return this.resultName; + } + + /** + * @return the results + */ + public List getResults() + { + return this.results; + } + + /** + * @return the searchedFor + */ + public boolean isSearchedFor() + { + return this.searchedFor; + } + + /** + * @return the spellCheckExist + */ + public boolean isSpellCheckExist() + { + return this.spellCheckExist; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/StatsParameters.java b/data-model/src/main/java/org/alfresco/service/cmr/search/StatsParameters.java new file mode 100644 index 0000000000..c4d91b5c81 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/StatsParameters.java @@ -0,0 +1,159 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.SearchParameters.SortDefinition; + +/** + * Defines Stats search criteria + * + * @author Gethin James + * @since 5.0 + */ +public class StatsParameters implements BasicSearchParameters +{ + public static final String PARAM_FIELD = "field"; + public static final String PARAM_FACET = "facet"; + public static final String FACET_PREFIX = "@"; + + private final String language; + private final String query; + private final String filterQuery; + private final boolean dateSearch; + private List stores = new ArrayList<>(); + private List locales = new ArrayList<>(); + private List sortDefinitions = new ArrayList<>(); + private Map statsParameters = new HashMap<>(); + + public StatsParameters(String language, String query) + { + this(language, query, null, false); + } + + public StatsParameters(String language, String query, boolean isDateSearch) + { + this(language, query, null, isDateSearch); + } + + public StatsParameters(String language, String query, String filterQuery, boolean isDateSearch) + { + super(); + this.language = language; + this.query = query; + this.filterQuery = filterQuery; + this.dateSearch = isDateSearch; + } + + public String getLanguage() + { + return this.language; + } + public String getQuery() + { + return this.query; + } + public String getFilterQuery() + { + return this.filterQuery; + } + public List getStores() + { + return this.stores; + } + public List getLocales() + { + return this.locales; + } + public List getSortDefinitions() + { + return this.sortDefinitions; + } + public Map getStatsParameters() + { + return this.statsParameters; + } + public boolean isDateSearch() + { + return this.dateSearch; + } + + /** + * Add a sort definition. + * + * @param sortDefinition - the sort definition to add. + */ + public void addSort(SortDefinition sortDefinition) + { + sortDefinitions.add(sortDefinition); + } + + /** + * Add a parameter + * + * @param name String + * @param value String + */ + public void addStatsParameter(String name, String value) + { + statsParameters.put(name, value); + } + + /** + * Add a Store ref + * + * @param store StoreRef + */ + public void addStore(StoreRef store) + { + if (stores.size() != 0) + { + throw new IllegalStateException("At the moment, there can only be one stats store set for the search"); + } + stores.add(store); + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("StatsParameters [query=").append(this.query).append(", filterquery=") + .append(this.filterQuery).append(", language=") + .append(this.language).append(", stores=").append(this.stores) + .append(", locales=").append(this.locales).append(", sortDefinitions=") + .append(this.sortDefinitions).append(", statsParameters=") + .append(this.statsParameters).append(", isDateSearch=") + .append(this.dateSearch).append("]"); + return builder.toString(); + } + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/StatsProcessor.java b/data-model/src/main/java/org/alfresco/service/cmr/search/StatsProcessor.java new file mode 100644 index 0000000000..dc3c378882 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/StatsProcessor.java @@ -0,0 +1,38 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +/** + * Post-Processors the results of a Stats query + * ie. for internationalization / transformation. + * + * @author Gethin James + * @since 5.0 + */ +public interface StatsProcessor +{ + public StatsResultSet process(StatsResultSet input); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/StatsProcessorUsingMap.java b/data-model/src/main/java/org/alfresco/service/cmr/search/StatsProcessorUsingMap.java new file mode 100644 index 0000000000..e299836bd7 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/StatsProcessorUsingMap.java @@ -0,0 +1,73 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.util.Map; + +/** + * Post-Processors the results of a Stats query using a Map of values. + * Looks up the value by Map.key and replaces it with Map.value + * + * If its not found then returns the existing value. + * + * @author Gethin James + * @since 5.0 + */ +public class StatsProcessorUsingMap implements StatsProcessor +{ + Map mapping; + + public StatsProcessorUsingMap() + { + super(); + } + + public StatsProcessorUsingMap(Map mapping) + { + super(); + this.mapping = mapping; + } + + @Override + public StatsResultSet process(StatsResultSet input) + { + if (input == null || input.getStats() == null){ return null; } + + for (StatsResultStat aStat : input.getStats()) + { + String processed = mapping.get(aStat.getName()); + if (processed != null) { aStat.setName(processed); } + } + return input; + } + + public void setMapping(Map mapping) + { + this.mapping = mapping; + } + + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/StatsRequestParameters.java b/data-model/src/main/java/org/alfresco/service/cmr/search/StatsRequestParameters.java new file mode 100644 index 0000000000..164660146b --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/StatsRequestParameters.java @@ -0,0 +1,183 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2017 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.util.Collections; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * POJO class representing Stats request + */ +public class StatsRequestParameters +{ + private final String field; + private final String label; + private final List percentiles; + private final Boolean min; + private final Boolean max; + private final Boolean sum; + private final Boolean countValues; + private final Boolean missing; + private final Boolean sumOfSquares; + private final Boolean mean; + private final Boolean stddev; + private final Boolean distinctValues; + private final Boolean countDistinct; + private final Boolean cardinality; + private final Float cardinalityAccuracy; + private final List excludeFilters; + + @JsonCreator + public StatsRequestParameters( + @JsonProperty("field") String field, + @JsonProperty("label") String label, + @JsonProperty("percentiles") List percentiles, + @JsonProperty("min") Boolean min, + @JsonProperty("max") Boolean max, + @JsonProperty("sum") Boolean sum, + @JsonProperty("countValues") Boolean countValues, + @JsonProperty("missing") Boolean missing, + @JsonProperty("sumOfSquares") Boolean sumOfSquares, + @JsonProperty("mean") Boolean mean, + @JsonProperty("stddev") Boolean stddev, + @JsonProperty("distinctValues") Boolean distinctValues, + @JsonProperty("countDistinct") Boolean countDistinct, + @JsonProperty("cardinality") Boolean cardinality, + @JsonProperty("cardinalityAccuracy") Float cardinalityAccuracy, + @JsonProperty("excludeFilters") List excludeFilters) + { + this.field = field; + this.label = label; + this.percentiles = percentiles == null? Collections.emptyList():percentiles; + + this.min = min == null?true:min; + this.max = max == null?true:max; + this.sum = sum == null?true:sum; + this.countValues = countValues == null?true:countValues; + this.missing = missing == null?true:missing; + this.sumOfSquares = sumOfSquares == null?true:sumOfSquares; + this.mean = mean == null?true:mean; + this.stddev = stddev == null?true:stddev; + + this.distinctValues = distinctValues == null?false:distinctValues; + this.countDistinct = countDistinct == null?false:countDistinct; + this.cardinality = cardinality == null?false:cardinality; + this.cardinalityAccuracy = cardinalityAccuracy == null?0.3f:cardinalityAccuracy; + this.excludeFilters = excludeFilters == null? Collections.emptyList():excludeFilters; + } + + public String getField() + { + return field; + } + + public String getLabel() + { + return label; + } + + public List getPercentiles() + { + return percentiles; + } + + public Boolean getDistinctValues() + { + return distinctValues; + } + + public Boolean getCountDistinct() + { + return countDistinct; + } + + public Boolean getCardinality() + { + return cardinality; + } + + public Float getCardinalityAccuracy() + { + return cardinalityAccuracy; + } + + public List getExcludeFilters() + { + return excludeFilters; + } + + public Boolean getMin() + { + return min; + } + + public Boolean getMax() + { + return max; + } + + public Boolean getSum() + { + return sum; + } + + public Boolean getCountValues() + { + return countValues; + } + + public Boolean getMissing() + { + return missing; + } + + public Boolean getSumOfSquares() + { + return sumOfSquares; + } + + public Boolean getMean() + { + return mean; + } + + public Boolean getStddev() + { + return stddev; + } + + @Override + public String toString() + { + return "StatsRequestParameters{" + "field='" + field + '\'' + ", label='" + label + '\'' + ", percentiles=" + percentiles + ", min=" + min + + ", max=" + max + ", sum=" + sum + ", countValues=" + countValues + ", missing=" + missing + ", sumOfSquares=" + sumOfSquares + ", mean=" + + mean + ", stddev=" + stddev + ", distinctValues=" + distinctValues + ", countDistinct=" + countDistinct + ", cardinality=" + + cardinality + ", cardinalityAccuracy=" + cardinalityAccuracy + ", excludeFilters=" + excludeFilters + '}'; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/StatsResultSet.java b/data-model/src/main/java/org/alfresco/service/cmr/search/StatsResultSet.java new file mode 100644 index 0000000000..f121e95cc3 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/StatsResultSet.java @@ -0,0 +1,43 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import java.util.List; + +/** + * A result of a search for Stats + * + * @author Gethin James + * @since 5.0 + */ +public interface StatsResultSet +{ + long getNumberFound(); //long For compatibility with SolrJSONResultSet + Long getSum(); + Long getMax(); + Long getMean(); + List getStats(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/StatsResultStat.java b/data-model/src/main/java/org/alfresco/service/cmr/search/StatsResultStat.java new file mode 100644 index 0000000000..13bc36feb7 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/StatsResultStat.java @@ -0,0 +1,101 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +/** + * Basic POJO to represent an individual statistic + * + * @author Gethin James + * @since 5.0 + */ +public class StatsResultStat { + + private String name; + private final Long sum; + private final Long count; + private final Long min; + private final Long max; + private final Long mean; + + public StatsResultStat(String name, Long sum, Long count, Long min, Long max, Long mean) + { + super(); + this.name = name; + this.sum = sum; + this.count = count; + this.min = min; + this.max = max; + this.mean = mean; + } + + public String getName() + { + return this.name; + } + + public Long getSum() + { + return this.sum; + } + + public Long getCount() + { + return this.count; + } + + public Long getMin() + { + return this.min; + } + + public Long getMax() + { + return this.max; + } + + public Long getMean() + { + return this.mean; + } + + public void setName(String name) + { + this.name = name; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Stat [name=").append(this.name).append(", sum=").append(this.sum) + .append(", count=").append(this.count).append(", min=").append(this.min) + .append(", max=").append(this.max).append(", mean=").append(this.mean) + .append("]"); + return builder.toString(); + } + + +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/service/cmr/search/StatsService.java b/data-model/src/main/java/org/alfresco/service/cmr/search/StatsService.java new file mode 100644 index 0000000000..798c26be42 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/search/StatsService.java @@ -0,0 +1,42 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; +/** + * + * A service that returns stats about the Alfresco repository + * + * @author Gethin James + * @since 5.0 + */ +public interface StatsService +{ + /** + * Query the repository for information + * @param searchParameters parameter to use + * @return StatsResultSet results of the search + */ + StatsResultSet query(StatsParameters searchParameters); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/security/AccessPermission.java b/data-model/src/main/java/org/alfresco/service/cmr/security/AccessPermission.java new file mode 100644 index 0000000000..e6d710587f --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/security/AccessPermission.java @@ -0,0 +1,90 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.security; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * The interface used to support reporting back if permissions are allowed or + * denied. + * + * @author Andy Hind + */ +@AlfrescoPublicApi +public interface AccessPermission +{ + /** + * The permission. + * + * @return String + */ + public String getPermission(); + + /** + * Get the Access enumeration value + * + * @return AccessStatus + */ + public AccessStatus getAccessStatus(); + + + /** + * Get the authority to which this permission applies. + * + * @return String + */ + public String getAuthority(); + + + /** + * Get the type of authority to which this permission applies. + * + * @return AuthorityType + */ + public AuthorityType getAuthorityType(); + + + /** + * At what position in the inheritance chain for permissions is this permission set? + * = 0 -> Set direct on the object. + * > 0 -> Inherited + * < 0 -> We don't know and are using this object for reporting (e.g. the actual permissions that apply to a node for the current user) + * @return int + */ + public int getPosition(); + + /** + * Is this an inherited permission entry? + * @return boolean + */ + public boolean isInherited(); + + /** + * Is this permission set on the object? + * @return boolean + */ + public boolean isSetDirectly(); +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/security/AccessStatus.java b/data-model/src/main/java/org/alfresco/service/cmr/security/AccessStatus.java new file mode 100644 index 0000000000..78e36bff1f --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/security/AccessStatus.java @@ -0,0 +1,39 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.security; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Enumeration used to indicate access status. + * + * @author Andy Hind + */ +@AlfrescoPublicApi +public enum AccessStatus +{ + DENIED, ALLOWED, UNDETERMINED; +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/security/AuthorityType.java b/data-model/src/main/java/org/alfresco/service/cmr/security/AuthorityType.java new file mode 100644 index 0000000000..00b2e8880c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/security/AuthorityType.java @@ -0,0 +1,625 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.security; + + + +import org.alfresco.api.AlfrescoPublicApi; + + + +/** + + * The types of authority that are available. + + *

    + + *

    + + * Available types are: + + *
      + + *
    1. USER - an authority that identifies a user + + *
    2. GROUP - an authority that identifies a group + + *
    3. OWNER - the special authority that applies to the owner of a node + + *
    4. EVERYONE - the special authority that is interpreted as everyone + + *
    5. GUEST - the special authority that applies to a GUEST (An unknown, unauthenticated user) + + *
    6. WILDCARD - the set of all authorities (including the guest user) + + *
    + + * + + * @author Andy Hind + + */ + +@AlfrescoPublicApi + +public enum AuthorityType + +{ + + ADMIN + + { + + public boolean isFixedString() + + { + + return true; + + } + + + + public String getFixedString() + + { + + return PermissionService.ADMINISTRATOR_AUTHORITY; + + } + + + + public boolean isPrefixed() + + { + + return false; + + } + + + + public String getPrefixString() + + { + + return ""; + + } + + + + public int getOrderPosition() + + { + + return 0; + + } + + }, + + + + EVERYONE + + { + + public boolean isFixedString() + + { + + return true; + + } + + + + public String getFixedString() + + { + + return PermissionService.ALL_AUTHORITIES; + + } + + + + public boolean isPrefixed() + + { + + return false; + + } + + + + public String getPrefixString() + + { + + return ""; + + } + + + + public int getOrderPosition() + + { + + return 1; + + } + + }, + + OWNER + + { + + public boolean isFixedString() + + { + + return true; + + } + + + + public String getFixedString() + + { + + return PermissionService.OWNER_AUTHORITY; + + } + + + + public boolean isPrefixed() + + { + + return false; + + } + + + + public String getPrefixString() + + { + + return ""; + + } + + + + public int getOrderPosition() + + { + + return 2; + + } + + }, + + GUEST + + { + + public boolean isFixedString() + + { + + return true; + + } + + + + public String getFixedString() + + { + + return PermissionService.GUEST_AUTHORITY; + + } + + + + public boolean isPrefixed() + + { + + return false; + + } + + + + public String getPrefixString() + + { + + return ""; + + } + + + + public int getOrderPosition() + + { + + return 3; + + } + + }, + + GROUP + + { + + public boolean isFixedString() + + { + + return false; + + } + + + + public String getFixedString() + + { + + return ""; + + } + + + + public boolean isPrefixed() + + { + + return true; + + } + + + + public String getPrefixString() + + { + + return PermissionService.GROUP_PREFIX; + + } + + + + public int getOrderPosition() + + { + + return 4; + + } + + }, + + ROLE + + { + + + + public boolean isFixedString() + + { + + return false; + + } + + + + public String getFixedString() + + { + + return ""; + + } + + + + public boolean isPrefixed() + + { + + return true; + + } + + + + public String getPrefixString() + + { + + return PermissionService.ROLE_PREFIX; + + } + + + + public int getOrderPosition() + + { + + return 5; + + } + + }, + + USER + + { + + public boolean isFixedString() + + { + + return false; + + } + + + + public String getFixedString() + + { + + return ""; + + } + + + + public boolean isPrefixed() + + { + + return false; + + } + + + + public String getPrefixString() + + { + + return ""; + + } + + + + public int getOrderPosition() + + { + + return 6; + + } + + }, + + WILDCARD + + { + + public boolean isFixedString() + + { + + return false; + + } + + + + public String getFixedString() + + { + + return ""; + + } + + + + public boolean isPrefixed() + + { + + return false; + + } + + + + public String getPrefixString() + + { + + return ""; + + } + + + + public int getOrderPosition() + + { + + return 7; + + } + + }; + + + + public abstract boolean isFixedString(); + + + + public abstract String getFixedString(); + + + + public abstract boolean isPrefixed(); + + + + public abstract String getPrefixString(); + + + + public abstract int getOrderPosition(); + + + + public boolean equals(String authority) + + { + + return equals(getAuthorityType(authority)); + + } + + + + public static AuthorityType getAuthorityType(String authority) + + { + + AuthorityType authorityType; + + + + if(null == authority) + + { + + authorityType = AuthorityType.WILDCARD; + + } + + else + + { + + if (authority.equals(PermissionService.ADMINISTRATOR_AUTHORITY)) + + { + + authorityType = AuthorityType.ADMIN; + + } + + if (authority.equals(PermissionService.ALL_AUTHORITIES)) + + { + + authorityType = AuthorityType.EVERYONE; + + } + + else if (authority.equals(PermissionService.OWNER_AUTHORITY)) + + { + + authorityType = AuthorityType.OWNER; + + } + + else if (authority.equalsIgnoreCase(PermissionService.GUEST_AUTHORITY)) + + { + + authorityType = AuthorityType.GUEST; + + } + + else if (authority.startsWith(PermissionService.GROUP_PREFIX)) + + { + + authorityType = AuthorityType.GROUP; + + } + + else if (authority.startsWith(PermissionService.ROLE_PREFIX)) + + { + + authorityType = AuthorityType.ROLE; + + } + + else + + { + + authorityType = AuthorityType.USER; + + } + + } + + + + return authorityType; + + } + +} + diff --git a/data-model/src/main/java/org/alfresco/service/cmr/security/PermissionContext.java b/data-model/src/main/java/org/alfresco/service/cmr/security/PermissionContext.java new file mode 100644 index 0000000000..884fb80179 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/security/PermissionContext.java @@ -0,0 +1,105 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.security; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.namespace.QName; + +@AlfrescoPublicApi +public class PermissionContext +{ + private QName type; + + private HashSet aspects = new HashSet(); + + private Map properties = new HashMap(); + + private Map> dynamicAuthorityAssignment = new HashMap>(); + + private Map additionalContext = new HashMap(); + + private Long storeAcl = null; + + public PermissionContext(QName type) + { + this.type = type; + } + + public HashSet getAspects() + { + return aspects; + } + + public Map> getDynamicAuthorityAssignment() + { + return dynamicAuthorityAssignment; + } + + public void addDynamicAuthorityAssignment(String user, String dynamicAuthority) + { + Set dynamicAuthorities = dynamicAuthorityAssignment.get(user); + if(dynamicAuthorities == null) + { + dynamicAuthorities = new HashSet(); + dynamicAuthorityAssignment.put(user, dynamicAuthorities); + } + dynamicAuthorities.add(dynamicAuthority); + } + + public Map getAdditionalContext() + { + return additionalContext; + } + + public Map getProperties() + { + return properties; + } + + public QName getType() + { + return type; + } + + public Long getStoreAcl() + { + return storeAcl; + } + + public void setStoreAcl(Long storeAcl) + { + this.storeAcl = storeAcl; + } + + + +} diff --git a/data-model/src/main/java/org/alfresco/service/cmr/security/PermissionService.java b/data-model/src/main/java/org/alfresco/service/cmr/security/PermissionService.java new file mode 100644 index 0000000000..7e74dcd67d --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/cmr/security/PermissionService.java @@ -0,0 +1,368 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.security; + +import java.util.Set; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.Auditable; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.namespace.QName; + +/** + * The public API for a permission service The implementation may be changed in the application configuration + * + * @author Andy Hind + */ +@AlfrescoPublicApi +public interface PermissionService +{ + /** + * Prefixes used for authorities of type role. This is intended for external roles, e.g. those set by ACEGI + * implementations It is only used for admin at the moment - which is done outside the usual permission assignments + * at the moment. It could be a dynamic authority. + */ + public static final String ROLE_PREFIX = "ROLE_"; + + /** + * Prefix used for authorities of type group. + */ + public static final String GROUP_PREFIX = "GROUP_"; + + /** + * The group that contains everyone except guest. + */ + public static final String ALL_AUTHORITIES = "GROUP_EVERYONE"; + + /** + * The dynamic authority used for ownership + */ + public static final String OWNER_AUTHORITY = "ROLE_OWNER"; + + /** + * The dynamic authority used for the ownership of locks. + */ + public static final String LOCK_OWNER_AUTHORITY = "ROLE_LOCK_OWNER"; + + /** + * The admin authority - currently a role. + */ + public static final String ADMINISTRATOR_AUTHORITY = "ROLE_ADMINISTRATOR"; + + /** + * The guest authority + */ + public static final String GUEST_AUTHORITY = "ROLE_GUEST"; + + /** + * The permission for all - not defined in the model. Repsected in the code. + */ + public static final String ALL_PERMISSIONS = "All"; + + // Constants for permissions/permission groups defined in the standard permission model. + + public static final String FULL_CONTROL = "FullControl"; + + public static final String READ = "Read"; + + public static final String WRITE = "Write"; + + public static final String DELETE = "Delete"; + + public static final String ADD_CHILDREN = "AddChildren"; + + public static final String READ_PROPERTIES = "ReadProperties"; + + public static final String READ_CHILDREN = "ReadChildren"; + + public static final String WRITE_PROPERTIES = "WriteProperties"; + + public static final String DELETE_NODE = "DeleteNode"; + + public static final String DELETE_CHILDREN = "DeleteChildren"; + + public static final String CREATE_CHILDREN = "CreateChildren"; + + public static final String LINK_CHILDREN = "LinkChildren"; + + public static final String DELETE_ASSOCIATIONS = "DeleteAssociations"; + + public static final String READ_ASSOCIATIONS = "ReadAssociations"; + + public static final String CREATE_ASSOCIATIONS = "CreateAssociations"; + + public static final String READ_PERMISSIONS = "ReadPermissions"; + + public static final String CHANGE_PERMISSIONS = "ChangePermissions"; + + public static final String EXECUTE = "Execute"; + + public static final String READ_CONTENT = "ReadContent"; + + public static final String WRITE_CONTENT = "WriteContent"; + + public static final String EXECUTE_CONTENT = "ExecuteContent"; + + public static final String TAKE_OWNERSHIP = "TakeOwnership"; + + public static final String SET_OWNER = "SetOwner"; + + public static final String COORDINATOR = "Coordinator"; + + public static final String CONTRIBUTOR = "Contributor"; + + public static final String EDITOR = "Editor"; + + public static final String CONSUMER = "Consumer"; + + public static final String LOCK = "Lock"; + + public static final String UNLOCK = "Unlock"; + + public static final String CHECK_OUT = "CheckOut"; + + public static final String CHECK_IN = "CheckIn"; + + public static final String CANCEL_CHECK_OUT = "CancelCheckOut"; + + public static final String ASPECTS = "Aspects"; + + public static final String PROPERTIES = "Properties"; + + /** + * Get the Owner Authority + * + * @return the owner authority + */ + @Auditable + public String getOwnerAuthority(); + + /** + * Get the All Authorities + * + * @return the All authorities + */ + @Auditable + public String getAllAuthorities(); + + /** + * Get the All Permission + * + * @return the All permission + */ + @Auditable + public String getAllPermission(); + + /** + * Get all the AccessPermissions that are granted/denied to the current authentication for the given node + * + * @param nodeRef - + * the reference to the node + * @return the set of allowed permissions + */ + @Auditable(parameters = { "nodeRef" }) + public Set getPermissions(NodeRef nodeRef); + + /** + * Get all the AccessPermissions that are set for anyone for the given node + * + * @param nodeRef - + * the reference to the node + * @return the set of allowed permissions + */ + @Auditable(parameters = { "nodeRef" }) + public Set getAllSetPermissions(NodeRef nodeRef); + + /** + * Get the permissions that can be set for a given node + */ + @Auditable(parameters = { "nodeRef" }) + public Set getSettablePermissions(NodeRef nodeRef); + + /** + * Get the permissions that can be set for a given type + * + * @return - set of permissions + */ + @Auditable(parameters = { "type" }) + public Set getSettablePermissions(QName type); + + /** + * Check that the given authentication has a particular permission for the given node. (The default behaviour is to + * inherit permissions) + * + * @return - access status + */ + @Auditable(parameters = { "nodeRef", "permission" }) + public AccessStatus hasPermission(NodeRef nodeRef, String permission); + + /** + * Check if read permission is allowed on an acl (optimised) + * + * caveats: + * doesn't take into account dynamic authorities/groups + * doesn't take into account node types/aspects for permissions + * + * @param nodeRef - + * the reference to the node + * @return access status + */ + @Auditable(parameters = { "nodeRef" }) + public AccessStatus hasReadPermission(NodeRef nodeRef); + + /** + * Get the readers associated with a given ACL + * + * @param aclId the low-level ACL ID + * @return set of authorities with read permission on the ACL + */ + @Auditable(parameters = { "aclId" }) + public Set getReaders(Long aclId); + + /** + * Get the denied authorities associated with a given ACL + * + * @param aclId the low-level ACL ID + * @return set of authorities denied permission on the ACL + */ + @Auditable(parameters = { "aclId" }) + public Set getReadersDenied(Long aclId); + + /** + * Check if a permission is allowed on an acl. + * @return the access status + */ + @Auditable(parameters = { "aclID", "context", "permission" }) + public AccessStatus hasPermission(Long aclID, PermissionContext context, String permission); + + /** + * Delete all the permission assigned to the node + */ + @Auditable(parameters = { "nodeRef" }) + public void deletePermissions(NodeRef nodeRef); + + /** + * Delete all permission for the given authority. + * + * @param authority + * (if null then this will match all authorities) + */ + @Auditable(parameters = { "nodeRef", "authority" }) + public void clearPermission(NodeRef nodeRef, String authority); + + /** + * Find and delete a access control entry by node, authentication and permission. It is possible to delete + *
      + *
    1. a specific permission; + *
    2. all permissions for an authority (if the permission is null); + *
    3. entries for all authorities that have a specific permission (if the authority is null); and + *
    4. all permissions set for the node (if both the permission and authority are null). + *
    + * + * @param nodeRef + * the node that the entry applies to + * @param authority + * the authority recipient (if null then this will match all authorities) + * @param permission + * the entry permission (if null then this will match all permissions) + */ + @Auditable(parameters = { "nodeRef", "authority", "permission" }) + public void deletePermission(NodeRef nodeRef, String authority, String permission); + + /** + * Set a specific permission on a node. + */ + @Auditable(parameters = { "nodeRef", "authority", "permission", "allow" }) + public void setPermission(NodeRef nodeRef, String authority, String permission, boolean allow); + + /** + * Set the global inheritance behaviour for permissions on a node. + */ + @Auditable(parameters = { "nodeRef", "inheritParentPermissions" }) + public void setInheritParentPermissions(NodeRef nodeRef, boolean inheritParentPermissions); + + /** + * Set the global inheritance behavior for permissions on a node. If the operation takes + * too long and asyncCall parameter set accordingly, fixed ACLs method will be asynchronously called. + * + * @param nodeRef node for which inheritance will be set. + * @param inheritParentPermissions true to inherit parent permissions, false otherwise. + * @param asyncCall true if fixed ACLs should be asynchronously set when operation execution takes too long, + * false to execute synchronously regardless of execution time. + */ + @Auditable(parameters = { "nodeRef", "inheritParentPermissions", "asyncCall" }) + public void setInheritParentPermissions(NodeRef nodeRef, boolean inheritParentPermissions, boolean asyncCall); + + /** + * Return the global inheritance behaviour for permissions on a node. + */ + @Auditable(parameters = { "nodeRef" }) + public boolean getInheritParentPermissions(NodeRef nodeRef); + + + /** + * Add a permission mask to a store + */ + @Auditable(parameters = { "storeRef", "authority", "permission", "allow" }) + public void setPermission(StoreRef storeRef, String authority, String permission, boolean allow); + + /** + * Remove part of a permission mask on a store + */ + @Auditable(parameters = { "storeRef", "authority", "permission" }) + public void deletePermission(StoreRef storeRef, String authority, String permission); + + /** + * Clear all permission masks for an authority on a store + */ + @Auditable(parameters = { "storeRef", "authority" }) + public void clearPermission(StoreRef storeRef, String authority); + + /** + * Remove all permission mask on a store + */ + @Auditable(parameters = { "storeRef" }) + public void deletePermissions(StoreRef storeRef); + + + /** + * Get all the AccessPermissions that are set for anyone for the given node + * + * @param storeRef - + * the reference to the store + * @return the set of allowed permissions + */ + @Auditable(parameters = { "storeRef" }) + public Set getAllSetPermissions(StoreRef storeRef); + + /** + * Get the set of authorities for currently authenticated user + * + * @return a set of authorities applying to the currently-authenticated user + */ + public Set getAuthorisations(); +} diff --git a/data-model/src/main/java/org/alfresco/service/namespace/DynamicNamespacePrefixResolver.java b/data-model/src/main/java/org/alfresco/service/namespace/DynamicNamespacePrefixResolver.java new file mode 100644 index 0000000000..918d52fa3d --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/namespace/DynamicNamespacePrefixResolver.java @@ -0,0 +1,145 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.namespace; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +/** + * A delegating namespace prefix resolver which allows local over rides from the + * delegate. Allows standard/default prefixes to be available but over ridden as + * required. + * + * @author andyh + */ +public class DynamicNamespacePrefixResolver implements NamespaceService +{ + /** + * The delegate + */ + private NamespacePrefixResolver delegate; + + /** + * The map uris keyed by prefix + */ + private HashMap map = new HashMap(); + + + public DynamicNamespacePrefixResolver(NamespacePrefixResolver delegate) + { + super(); + this.delegate = delegate; + } + + public DynamicNamespacePrefixResolver() + { + this(null); + } + + + /** + * Add prefix to name space mapping override + * + * @param prefix String + * @param uri String + */ + public void registerNamespace(String prefix, String uri) + { + map.put(prefix, uri); + } + + /** + * Remove a prefix to namespace mapping + * + * @param prefix String + */ + public void unregisterNamespace(String prefix) + { + map.remove(prefix); + } + + // NameSpacePrefix Resolver + + public String getNamespaceURI(String prefix) throws NamespaceException + { + String uri = map.get(prefix); + if ((uri == null) && (delegate != null)) + { + uri = delegate.getNamespaceURI(prefix); + } + return uri; + } + + public Collection getPrefixes(String namespaceURI) throws NamespaceException + { + Collection prefixes = new ArrayList(); + for (String key : map.keySet()) + { + String uri = map.get(key); + if ((uri != null) && (uri.equals(namespaceURI))) + { + prefixes.add(key); + } + } + // Only add if not over ridden here (if identical already added) + if (delegate != null) + { + for (String prefix : delegate.getPrefixes(namespaceURI)) + { + if (!map.containsKey(prefix)) + { + prefixes.add(prefix); + } + } + } + return prefixes; + } + + public Collection getPrefixes() + { + Set prefixes = new HashSet(); + if(delegate != null) + { + prefixes.addAll(delegate.getPrefixes()); + } + prefixes.addAll(map.keySet()); + return prefixes; + } + + public Collection getURIs() + { + Set uris = new HashSet(); + if(delegate != null) + { + uris.addAll(delegate.getURIs()); + } + uris.addAll(map.values()); + return uris; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/namespace/InvalidQNameException.java b/data-model/src/main/java/org/alfresco/service/namespace/InvalidQNameException.java new file mode 100644 index 0000000000..b61026ff51 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/namespace/InvalidQNameException.java @@ -0,0 +1,44 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.namespace; + +import org.alfresco.api.AlfrescoPublicApi; + +@AlfrescoPublicApi +public class InvalidQNameException extends NamespaceException +{ + private static final long serialVersionUID = 7851788938794302629L; + + public InvalidQNameException(String msg) + { + super(msg); + } + + public InvalidQNameException(String msg, Throwable cause) + { + super(msg, cause); + } +} diff --git a/data-model/src/main/java/org/alfresco/service/namespace/NamespaceException.java b/data-model/src/main/java/org/alfresco/service/namespace/NamespaceException.java new file mode 100644 index 0000000000..4280094578 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/namespace/NamespaceException.java @@ -0,0 +1,44 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.namespace; + +import org.alfresco.api.AlfrescoPublicApi; + +@AlfrescoPublicApi +public class NamespaceException extends RuntimeException +{ + private static final long serialVersionUID = 7851788938794302629L; + + public NamespaceException(String msg) + { + super(msg); + } + + public NamespaceException(String msg, Throwable cause) + { + super(msg, cause); + } +} diff --git a/data-model/src/main/java/org/alfresco/service/namespace/NamespacePrefixResolver.java b/data-model/src/main/java/org/alfresco/service/namespace/NamespacePrefixResolver.java new file mode 100644 index 0000000000..17f3ddae6c --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/namespace/NamespacePrefixResolver.java @@ -0,0 +1,81 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.namespace; + +import java.io.Serializable; +import java.util.Collection; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.Auditable; +import org.alfresco.service.PublicService; + +/** + * The NamespacePrefixResolver provides a mapping between + * namespace prefixes and namespace URIs. + * + * @author David Caruana + */ +@AlfrescoPublicApi +public interface NamespacePrefixResolver +{ + /** + * Gets the namespace URI registered for the given prefix + * + * @param prefix prefix to lookup + * @return the namespace + * @throws NamespaceException if prefix has not been registered + */ + @Auditable(parameters = {"prefix"}) + public String getNamespaceURI(String prefix) + throws NamespaceException; + + /** + * Gets the registered prefixes for the given namespace URI + * + * @param namespaceURI namespace URI to lookup + * @return the prefixes (or empty collection, if no prefixes registered against URI) + * @throws NamespaceException if URI has not been registered + */ + @Auditable(parameters = {"namespaceURI"}) + public Collection getPrefixes(String namespaceURI) + throws NamespaceException; + + /** + * Gets all registered Prefixes + * + * @return collection of all registered namespace prefixes + */ + @Auditable + Collection getPrefixes(); + + /** + * Gets all registered Uris + * + * @return collection of all registered namespace uris + */ + @Auditable + Collection getURIs(); +} diff --git a/data-model/src/main/java/org/alfresco/service/namespace/NamespacePrefixResolverProvider.java b/data-model/src/main/java/org/alfresco/service/namespace/NamespacePrefixResolverProvider.java new file mode 100644 index 0000000000..3a596b79e8 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/namespace/NamespacePrefixResolverProvider.java @@ -0,0 +1,45 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.namespace; + +import java.io.Serializable; + +/** + * Provides support for serializable objects such as the QNameMap that require a + * NamespacePrefixResolver to be available. Ensures that the objects can remain + * serializable themselves and still maintain a valid NamespacePrefixResolver. + * + * @author Kevin Roast + */ +public interface NamespacePrefixResolverProvider extends Serializable +{ + /** + * Get an object that implements the NamespacePrefixResolver interface + * + * @return NamespacePrefixResolver + */ + NamespacePrefixResolver getNamespacePrefixResolver(); +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/service/namespace/NamespaceService.java b/data-model/src/main/java/org/alfresco/service/namespace/NamespaceService.java new file mode 100644 index 0000000000..2e11398706 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/namespace/NamespaceService.java @@ -0,0 +1,168 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.namespace; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.Auditable; + +/** + * Namespace Service. + * + * The Namespace Service provides access to and definition of namespace + * URIs and Prefixes. + * + * @author David Caruana + */ +@AlfrescoPublicApi +public interface NamespaceService extends NamespacePrefixResolver +{ + /** Default Namespace URI */ + static final String DEFAULT_URI = ""; + + /** Default Namespace Prefix */ + static final String DEFAULT_PREFIX = ""; + + /** Default Alfresco URI */ + static final String ALFRESCO_URI = "http://www.alfresco.org"; + + /** Default Alfresco Prefix */ + static final String ALFRESCO_PREFIX = "alf"; + + /** Dictionary Model URI */ + static final String DICTIONARY_MODEL_1_0_URI = "http://www.alfresco.org/model/dictionary/1.0"; + + /** Dictionary Model Prefix */ + static final String DICTIONARY_MODEL_PREFIX = "d"; + + /** System Model URI */ + static final String SYSTEM_MODEL_1_0_URI = "http://www.alfresco.org/model/system/1.0"; + + /** System Model Prefix */ + static final String SYSTEM_MODEL_PREFIX = "sys"; + + /** Content Model URI */ + static final String CONTENT_MODEL_1_0_URI = "http://www.alfresco.org/model/content/1.0"; + + /** Content Model Prefix */ + static final String CONTENT_MODEL_PREFIX = "cm"; + + /** Application Model URI */ + static final String APP_MODEL_1_0_URI = "http://www.alfresco.org/model/application/1.0"; + + /** Application Model Prefix */ + static final String APP_MODEL_PREFIX = "app"; + + /** Audio Model URI */ + static final String AUDIO_MODEL_1_0_URI = "http://www.alfresco.org/model/audio/1.0"; + + /** Audio Model Prefix */ + static final String AUDIO_MODEL_PREFIX = "audio"; + + /** EXIF Model URI */ + static final String EXIF_MODEL_1_0_URI = "http://www.alfresco.org/model/exif/1.0"; + + /** WebDAV Model Prefix */ + static final String WEBDAV_MODEL_PREFIX = "webdav"; + + /** WebDAV Model URI */ + static final String WEBDAV_MODEL_1_0_URI = "http://www.alfresco.org/model/webdav/1.0"; + + /** EXIF Model Prefix */ + static final String EXIF_MODEL_PREFIX = "exif"; + + /** DataList Model URI */ + static final String DATALIST_MODEL_1_0_URI = "http://www.alfresco.org/model/datalist/1.0"; + + /** DataList Model Prefix */ + static final String DATALIST_MODEL_PREFIX = "dl"; + + /** Business Process Model URI */ + static final String BPM_MODEL_1_0_URI = "http://www.alfresco.org/model/bpm/1.0"; + + /** Business Process Model Prefix */ + static final String BPM_MODEL_PREFIX = "bpm"; + + /** Workflow Model URI */ + static final String WORKFLOW_MODEL_1_0_URI = "http://www.alfresco.org/model/workflow/1.0"; + + /** Workflow Model Prefix */ + static final String WORKFLOW_MODEL_PREFIX = "wf"; + + /** Alfresco Forums URI */ + static final String FORUMS_MODEL_1_0_URI = "http://www.alfresco.org/model/forum/1.0"; + + /** Alfresco Forums Prefix */ + static final String FORUMS_MODEL_PREFIX = "fm"; + + /** Alfresco Links URI */ + static final String LINKS_MODEL_1_0_URI = "http://www.alfresco.org/model/linksmodel/1.0"; + + /** Alfresco Links Prefix */ + static final String LINKS_MODEL_PREFIX = "lnk"; + + /** Rendition Model URI */ + static final String RENDITION_MODEL_1_0_URI = "http://www.alfresco.org/model/rendition/1.0"; + + /** Rendition Model Prefix */ + static final String RENDITION_MODEL_PREFIX = "rn"; + + /** Alfresco View Namespace URI */ + static final String REPOSITORY_VIEW_1_0_URI = "http://www.alfresco.org/view/repository/1.0"; + + /** Alfresco View Namespace Prefix */ + static final String REPOSITORY_VIEW_PREFIX = "view"; + + /** Alfresco security URI */ + static final String SECURITY_MODEL_1_0_URI = "http://www.alfresco.org/model/security/1.0"; + + /** Alfresco security Prefix */ + static final String SECURITY_MODEL_PREFIX = "security"; + + /** Email Server Application Model URI */ + static final String EMAILSERVER_MODEL_URI = "http://www.alfresco.org/model/emailserver/1.0"; + + /** Email Server Application Model Prefix */ + static final String EMAILSERVER_MODEL_PREFIX = "emailserver"; + + /** + * Register a prefix for namespace uri. + * + * @param prefix String + * @param uri String + */ + @Auditable(parameters = {"prefix", "uri"}) + public void registerNamespace(String prefix, String uri); + + + /** + * Unregister a prefix. + * + * @param prefix String + */ + @Auditable(parameters = {"prefix"}) + public void unregisterNamespace(String prefix); + +} diff --git a/data-model/src/main/java/org/alfresco/service/namespace/NamespaceServiceMemoryImpl.java b/data-model/src/main/java/org/alfresco/service/namespace/NamespaceServiceMemoryImpl.java new file mode 100644 index 0000000000..10eb7478e6 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/namespace/NamespaceServiceMemoryImpl.java @@ -0,0 +1,75 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.service.namespace; + +import java.util.Collection; + +import org.alfresco.util.OneToManyHashBiMap; + +/** + * A basic implementation of the NamespaceService interface intended for use in + * unit tests. This implementation does not persist any changes beyond the + * lifetime of the object. + * + * @author Nick Smith + */ +public class NamespaceServiceMemoryImpl implements NamespaceService +{ + // URI to Prefix map. + private final OneToManyHashBiMap map = new OneToManyHashBiMap(); + + public void registerNamespace(String prefix, String uri) + { + map.putSingleValue(uri, prefix); + } + + public void unregisterNamespace(String prefix) + { + map.removeValue(prefix); + } + + public String getNamespaceURI(String prefix) throws NamespaceException + { + return map.getKey(prefix); + } + + public Collection getPrefixes(String namespaceURI) throws NamespaceException + { + return map.get(namespaceURI); + } + + public Collection getPrefixes() + { + return map.flatValues(); + } + + public Collection getURIs() + { + return map.keySet(); + } + +} \ No newline at end of file diff --git a/data-model/src/main/java/org/alfresco/service/namespace/QName.java b/data-model/src/main/java/org/alfresco/service/namespace/QName.java new file mode 100644 index 0000000000..fda96c63c1 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/namespace/QName.java @@ -0,0 +1,528 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.namespace; + +import java.io.Serializable; +import java.util.Collection; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * QName represents the qualified name of a Repository item. Each + * QName consists of a local name qualified by a namespace. + *

    + * The {@link org.alfresco.service.namespace.QNamePattern QNamePattern} is implemented + * to allow instances of this class to be used for direct pattern matching where + * required on interfaces. + * + * @author David Caruana + */ +@AlfrescoPublicApi +public final class QName implements QNamePattern, Serializable, Cloneable, Comparable +{ + public static final String EMPTY_URI_SUBSTITUTE = ".empty"; + + private static final long serialVersionUID = 3977016258204348976L; + + private final String namespaceURI; // never null + private final String localName; // never null + private int hashCode; + private final String prefix; + + public static final char NAMESPACE_PREFIX = ':'; + public static final char NAMESPACE_BEGIN = '{'; + public static final char NAMESPACE_END = '}'; + public static final int MAX_LENGTH = 255; + + /** + * Create a QName + * + * (With no prefix) + * + * @param namespaceURI the qualifying namespace (maybe null or empty string) + * @param localName the local name + * @return the QName + */ + public static QName createQName(String namespaceURI, String localName) + throws InvalidQNameException + { + if (localName == null || localName.length() == 0) + { + throw new InvalidQNameException("A QName must consist of a local name"); + } + return new QName(namespaceURI, localName, null); + } + + + /** + * Create a QName + * + * @param prefix namespace prefix (maybe null or empty string) + * @param localName local name + * @param prefixResolver lookup to resolve mappings between prefix and namespace + * @return the QName + */ + public static QName createQName(String prefix, String localName, NamespacePrefixResolver prefixResolver) + throws InvalidQNameException, NamespaceException + { + // Validate Arguments + if (localName == null || localName.length() == 0) + { + throw new InvalidQNameException("A QName must consist of a local name"); + } + if (prefixResolver == null) + { + throw new IllegalArgumentException("A Prefix Resolver must be specified"); + } + if (prefix == null) + { + prefix = NamespaceService.DEFAULT_PREFIX; + } + + // Calculate namespace URI and create QName + String uri = prefixResolver.getNamespaceURI(prefix); + if (uri == null) + { + throw new NamespaceException("Namespace prefix " + prefix + " is not mapped to a namespace URI"); + } + return new QName(uri, localName, prefix); + } + + + /** + * Create a QName (from prefix format) prefix:localName + * + * @param qname qualified name of the following format prefix:localName + * @param prefixResolver lookup to resolve mappings between prefix and namespace + * @return the QName + */ + public static QName createQName(String qname, NamespacePrefixResolver prefixResolver) + throws InvalidQNameException, NamespaceException + { + QName name = null; + if (qname != null) + { + int colonIndex = qname.indexOf(NAMESPACE_PREFIX); + String prefix = (colonIndex == -1) ? NamespaceService.DEFAULT_PREFIX : qname.substring(0, colonIndex); + String localName = (colonIndex == -1) ? qname : qname.substring(colonIndex +1); + name = createQName(prefix, localName, prefixResolver); + } + return name; + } + + + /** + * Create a QName from its internal string representation of the following format: + * + * {namespaceURI}localName + * + * @param qname the string representation of the QName + * @return the QName + * @throws IllegalArgumentException + * @throws InvalidQNameException + */ + public static QName createQName(String qname) + throws InvalidQNameException + { + if (qname == null || qname.length() == 0) + { + throw new InvalidQNameException("Argument qname is mandatory"); + } + + String namespaceURI = null; + String localName = null; + + // Parse namespace + int namespaceBegin = qname.indexOf(NAMESPACE_BEGIN); + int namespaceEnd = -1; + if (namespaceBegin != -1) + { + if (namespaceBegin != 0) + { + throw new InvalidQNameException("QName '" + qname + "' must start with a namespaceURI"); + } + namespaceEnd = qname.indexOf(NAMESPACE_END, namespaceBegin + 1); + if (namespaceEnd == -1) + { + throw new InvalidQNameException("QName '" + qname + "' is missing the closing namespace " + NAMESPACE_END + " token"); + } + namespaceURI = qname.substring(namespaceBegin + 1, namespaceEnd); + } + + // Parse name + localName = qname.substring(namespaceEnd + 1); + if (localName == null || localName.length() == 0) + { + throw new InvalidQNameException("QName '" + qname + "' must consist of a local name"); + } + + // Construct QName + return new QName(namespaceURI, localName, null); + } + + /** + * Create a QName, optionally truncating the localname to {@link QName#MAX_LENGTH}. + * + * @param namespaceURI the qualifying namespace (maybe null or empty string) + * @param localName the local name, which will be truncated, if necessary + * @return the QName with potentially-truncated localname + */ + public static QName createQNameWithValidLocalName(final String namespaceURI, String localName) + { + return new QName(namespaceURI, QName.createValidLocalName(localName), null); + } + + /** + * Create a valid local name from the specified name + * + * @param name name to create valid local name from + * @return valid local name + */ + public static String createValidLocalName(String name) + { + // Validate length + if (name == null || name.length() == 0) + { + throw new IllegalArgumentException("Local name cannot be null or empty."); + } + if (name.length() > MAX_LENGTH) + { + name = name.substring(0, MAX_LENGTH); + } + + return name; + } + + /** + * Create a QName + * + * @param qname qualified name of the following format prefix:localName + * @return string array where index 0 => prefix and index 1 => local name + */ + public static String[] splitPrefixedQName(String qname) + throws InvalidQNameException, NamespaceException + { + if (qname != null) + { + int colonIndex = qname.indexOf(NAMESPACE_PREFIX); + String prefix = (colonIndex == -1) ? NamespaceService.DEFAULT_PREFIX : qname.substring(0, colonIndex); + String localName = (colonIndex == -1) ? qname : qname.substring(colonIndex +1); + return new String[] { prefix, localName }; + } + return null; + } + + + /** + * Construct QName + * + * @param namespace qualifying namespace (maybe null or empty string) + * @param name qualified name + * @param prefix prefix (maybe null or empty string) + */ + private QName(String namespace, String name, String prefix) + { + this.namespaceURI = ((namespace == null) || (namespace.equals(QName.EMPTY_URI_SUBSTITUTE))) ? NamespaceService.DEFAULT_URI : namespace; + this.prefix = prefix; + this.localName = name; + this.hashCode = 0; + } + + @Override + public Object clone() throws CloneNotSupportedException + { + return super.clone(); + } + + /** + * Gets the name + * + * @return the name + */ + public String getLocalName() + { + return this.localName; + } + + + /** + * Gets the namespace + * + * @return the namespace (empty string when not specified, but never null) + */ + public String getNamespaceURI() + { + return this.namespaceURI; + } + + + /** + * Gets a prefix resolved version of this QName + * + * @param resolver namespace prefix resolver + * @return QName with prefix resolved + */ + public QName getPrefixedQName(NamespacePrefixResolver resolver) + { + Collection prefixes = resolver.getPrefixes(namespaceURI); + if (prefixes.size() == 0) + { + throw new NamespaceException("A namespace prefix is not registered for uri " + namespaceURI); + } + String resolvedPrefix = prefixes.iterator().next(); + if (prefix != null && prefix.equals(resolvedPrefix)) + { + return this; + } + return new QName(namespaceURI, localName, resolvedPrefix); + } + + + /** + * Two QNames are equal only when both their name and namespace match. + * + * Note: The prefix is ignored during the comparison. + */ + @Override + public boolean equals(Object object) + { + if (this == object) + { + return true; + } + if (object instanceof QName) + { + QName other = (QName)object; + // namespaceURI and localname are not allowed to be null + return (this.localName.equals(other.localName) && + this.namespaceURI.equals(other.namespaceURI)); + } + return false; + } + + /** + * Performs a direct comparison between qnames. + * + * @see #equals(Object) + */ + public boolean isMatch(QName qname) + { + return this.equals(qname); + } + + /** + * Calculate hashCode. Follows pattern used by String where hashCode is + * cached (QName is immutable). + */ + @Override + public int hashCode() + { + if (this.hashCode == 0) + { + // the hashcode assignment is atomic - it is only an integer + this.hashCode = ((37 * localName.hashCode()) + namespaceURI.hashCode()); + } + return this.hashCode; + } + + + /** + * Render string representation of QName using format: + * + * {namespace}name + * + * @return the string representation + */ + @Override + public String toString() + { + return new StringBuilder(80).append(NAMESPACE_BEGIN) + .append(namespaceURI) + .append(NAMESPACE_END) + .append(localName).toString(); + } + + /** + * Uses the {@link #getNamespaceURI() namespace URI} and then the {@link #getLocalName() localname} + * to do the comparison i.e. the comparison is alphabetical. + */ + public int compareTo(QName qname) + { + int namespaceComparison = this.namespaceURI.compareTo(qname.namespaceURI); + if (namespaceComparison != 0) + { + return namespaceComparison; + } + // Namespaces are the same. Do comparison on localname + return this.localName.compareTo(qname.localName); + } + + + /** + * Render string representation of QName using format: + * + * prefix:name + * + * @return the string representation + */ + public String toPrefixString() + { + return (prefix == null) ? localName : prefix + NAMESPACE_PREFIX + localName; + } + + + /** + * Getter version of toPrefixString() + * + * @return the string representation of QName + */ + public String getPrefixString() + { + return toPrefixString(); + } + + + /** + * Render string representation of QName using format: + * + * prefix:name + * + * according to namespace prefix mappings of specified namespace resolver. + * + * @param prefixResolver namespace prefix resolver + * + * @return the string representation + */ + public String toPrefixString(NamespacePrefixResolver prefixResolver) + { + Collection prefixes = prefixResolver.getPrefixes(namespaceURI); + if (prefixes.size() == 0) + { + throw new NamespaceException("A namespace prefix is not registered for uri " + namespaceURI); + } + String pref = prefixes.iterator().next(); + if (pref.equals(NamespaceService.DEFAULT_PREFIX)) + { + return localName; + } + else + { + return pref + NAMESPACE_PREFIX + localName; + } + } + + + /** + * Creates a QName representation for the given String. If the String has no namespace the Alfresco namespace is + * added. If the String has a prefix an attempt to resolve the prefix to the full URI will be made. + * + * @param str The string to convert + * @return A QName representation of the given string + */ + public static QName resolveToQName(NamespacePrefixResolver prefixResolver, String str) + { + QName qname = null; + + if (str == null || str.length() == 0) + { + throw new IllegalArgumentException("str parameter is mandatory"); + } + + if (str.charAt(0) == (NAMESPACE_BEGIN)) + { + // create QName directly + qname = createQName(str); + } + else if (str.indexOf(NAMESPACE_PREFIX) != -1) + { + // extract the prefix and try and resolve using the + // namespace service + int end = str.indexOf(NAMESPACE_PREFIX); + String prefix = str.substring(0, end); + String localName = str.substring(end + 1); + String uri = prefixResolver.getNamespaceURI(prefix); + + if (uri != null) + { + qname = createQName(uri, localName); + } + } + else + { + // there's no namespace so prefix with Alfresco's Content Model + qname = createQName(NamespaceService.CONTENT_MODEL_1_0_URI, str); + } + + return qname; + } + + + /** + * Creates a string representation of a QName for the given string. If the given string already has a namespace, + * either a URL or a prefix, nothing the given string is returned. If it does not have a namespace the Alfresco + * namespace is added. + * + * @param str + * The string to convert + * + * @return A QName String representation of the given string + */ + public static String resolveToQNameString(NamespacePrefixResolver prefixResolver, String str) + { + String result = str; + + if (str == null || str.length() == 0) + { + throw new IllegalArgumentException("str parameter is mandatory"); + } + + if (str.charAt(0) != NAMESPACE_BEGIN) + { + if (str.indexOf(NAMESPACE_PREFIX) != -1) + { + // get the prefix and resolve to the uri + int end = str.indexOf(NAMESPACE_PREFIX); + String prefix = str.substring(0, end); + String localName = str.substring(end + 1); + String uri = prefixResolver.getNamespaceURI(prefix); + + if (uri != null) + { + result = new StringBuilder(64).append(NAMESPACE_BEGIN).append(uri).append(NAMESPACE_END) + .append(localName).toString(); + } + } + else + { + // there's no namespace so prefix with Alfresco's Content Model + result = new StringBuilder(64).append(NAMESPACE_BEGIN).append(NamespaceService.CONTENT_MODEL_1_0_URI) + .append(NAMESPACE_END).append(str).toString(); + } + } + + return result; + } +} diff --git a/data-model/src/main/java/org/alfresco/service/namespace/QNameCache.java b/data-model/src/main/java/org/alfresco/service/namespace/QNameCache.java new file mode 100644 index 0000000000..7027064d76 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/namespace/QNameCache.java @@ -0,0 +1,140 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.service.namespace; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; + +/** + * @author Nick Smith + * @since 4.0 + */ +public class QNameCache +{ + private final int maxSize; + private final Map qNameToNameCache = new HashMap(); + private final Map nameToQNameCache = new HashMap(); + + private final ReentrantReadWriteLock qNameToNameLock = new ReentrantReadWriteLock(); + private final WriteLock qNameToNameWriteLock = qNameToNameLock.writeLock(); + private final ReadLock qNameToNameReadLock = qNameToNameLock.readLock(); + + private final ReentrantReadWriteLock nameToQNameLock = new ReentrantReadWriteLock(); + private final WriteLock nameToQNameWriteLock = nameToQNameLock.writeLock(); + private final ReadLock nameToQNameReadLock = nameToQNameLock.readLock(); + + public QNameCache(int maxSize) + { + this.maxSize = maxSize; + } + + public String getName(QName qName) + { + qNameToNameReadLock.lock(); + try + { + return qNameToNameCache.get(qName); + } + finally + { + qNameToNameReadLock.unlock(); + } + } + + public void putQNameToName(QName qName, String name) + { + qNameToNameWriteLock.lock(); + try + { + if(qNameToNameCache.size()>maxSize) + { + qNameToNameCache.clear(); + } + qNameToNameCache.put(qName, name); + } + finally + { + qNameToNameWriteLock.unlock(); + } + } + + public QName getQName(String name) + { + nameToQNameReadLock.lock(); + try + { + if(nameToQNameCache.size()>maxSize) + { + nameToQNameCache.clear(); + } + return nameToQNameCache.get(name); + } + finally + { + nameToQNameReadLock.unlock(); + } + } + + public void putNameToQName(String name, QName qName) + { + nameToQNameWriteLock.lock(); + try + { + nameToQNameCache.put(name, qName); + } + finally + { + nameToQNameWriteLock.unlock(); + } + } + + public void clear() + { + nameToQNameWriteLock.lock(); + try + { + nameToQNameCache.clear(); + } + finally + { + nameToQNameWriteLock.unlock(); + } + qNameToNameWriteLock.lock(); + try + { + qNameToNameCache.clear(); + } + finally + { + qNameToNameWriteLock.unlock(); + } + + } +} diff --git a/data-model/src/main/java/org/alfresco/service/namespace/QNameMap.java b/data-model/src/main/java/org/alfresco/service/namespace/QNameMap.java new file mode 100644 index 0000000000..747dd186b1 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/namespace/QNameMap.java @@ -0,0 +1,219 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.namespace; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A Map that holds as it's key a QName stored in it's internal String representation. + * Calls to get and put automatically map the key to and from the QName representation. + * + * @author gavinc + */ +public class QNameMap implements Map, Cloneable, Serializable +{ + private static final long serialVersionUID = -6578946123712939602L; + + protected static Log logger = LogFactory.getLog(QNameMap.class); + protected Map contents = new HashMap(16, 1.0f); + protected NamespacePrefixResolverProvider provider = null; + + + /** + * Constructor + * + * @param provider Mandatory NamespacePrefixResolverProvider helper + */ + public QNameMap(NamespacePrefixResolverProvider provider) + { + if (provider == null) + { + throw new IllegalArgumentException("NamespacePrefixResolverProvider is mandatory."); + } + this.provider = provider; + } + + /** + * Constructor for Serialization mechanism + */ + protected QNameMap() + { + super(); + } + + + /** + * Helper to return a NamespacePrefixResolver instance - should -always- be used + * rather than holding onto a reference on the heap. + * + * @return NamespacePrefixResolver + */ + protected final NamespacePrefixResolver getResolver() + { + return this.provider.getNamespacePrefixResolver(); + } + + /** + * @see java.util.Map#size() + */ + public final int size() + { + return this.contents.size(); + } + + /** + * @see java.util.Map#isEmpty() + */ + public boolean isEmpty() + { + return this.contents.isEmpty(); + } + + /** + * @see java.util.Map#containsKey(java.lang.Object) + */ + public boolean containsKey(Object key) + { + return (this.contents.containsKey(QName.resolveToQNameString(getResolver(), key.toString()))); + } + + /** + * @see java.util.Map#containsValue(java.lang.Object) + */ + public boolean containsValue(Object value) + { + return this.contents.containsValue(value); + } + + /** + * @see java.util.Map#get(java.lang.Object) + */ + public Object get(Object key) + { + String qnameKey = QName.resolveToQNameString(getResolver(), key.toString()); + Object obj = this.contents.get(qnameKey); + + return obj; + } + + /** + * @see java.util.Map#put(Object, Object) + */ + public Object put(Object key, Object value) + { + return this.contents.put(QName.resolveToQNameString(getResolver(), key.toString()), value); + } + + /** + * @see java.util.Map#remove(java.lang.Object) + */ + public Object remove(Object key) + { + return this.contents.remove(QName.resolveToQNameString(getResolver(), key.toString())); + } + + /** + * @see java.util.Map#putAll(java.util.Map) + */ + public void putAll(Map t) + { + for (Object key : t.keySet()) + { + this.put(key, t.get(key)); + } + } + + /** + * @see java.util.Map#clear() + */ + public void clear() + { + this.contents.clear(); + } + + /** + * @see java.util.Map#keySet() + */ + public Set keySet() + { + return this.contents.keySet(); + } + + /** + * @see java.util.Map#values() + */ + public Collection values() + { + return this.contents.values(); + } + + /** + * @see java.util.Map#entrySet() + */ + public Set entrySet() + { + return this.contents.entrySet(); + } + + /** + * Override Object.toString() to provide useful debug output + */ + public String toString() + { + return this.contents.toString(); + } + + /** + * Shallow copy the map by copying keys and values into a new QNameMap + */ + public Object clone() + { + QNameMap map = new QNameMap(provider); + map.putAll(this); + + return map; + } + + @SuppressWarnings("unchecked") + public Map getMapOfQNames() + { + HashMap map = new HashMap(contents.size()); + for (Entry entry : contents.entrySet()) + { + QName key = QName.createQName(entry.getKey()); + map.put(key, (V)entry.getValue()); + } + return map; + } + +} diff --git a/data-model/src/main/java/org/alfresco/service/namespace/QNamePattern.java b/data-model/src/main/java/org/alfresco/service/namespace/QNamePattern.java new file mode 100644 index 0000000000..405a94d882 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/namespace/QNamePattern.java @@ -0,0 +1,52 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.namespace; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Provides pattern matching against {@link org.alfresco.service.namespace.QName qnames}. + *

    + * Implementations will use different mechanisms to match against the + * {@link org.alfresco.service.namespace.QName#getNamespaceURI() namespace} and + * {@link org.alfresco.service.namespace.QName#getLocalName()() localname}. + * + * @see org.alfresco.service.namespace.QName + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public interface QNamePattern +{ + /** + * Checks if the given qualified name matches the pattern represented + * by this instance + * + * @param qname the instance to check + * @return Returns true if the qname matches this pattern + */ + public boolean isMatch(QName qname); +} diff --git a/data-model/src/main/java/org/alfresco/service/namespace/RegexQNamePattern.java b/data-model/src/main/java/org/alfresco/service/namespace/RegexQNamePattern.java new file mode 100644 index 0000000000..d3e04633e4 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/service/namespace/RegexQNamePattern.java @@ -0,0 +1,149 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.namespace; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.alfresco.api.AlfrescoPublicApi; + +/** + * Provides matching between {@link org.alfresco.service.namespace.QName qnames} using + * regular expression matching. + *

    + * A simple {@link #MATCH_ALL convenience} pattern matcher is also provided that + * will match any qname. + * + * @see java.lang.String#matches(java.lang.String) + * + * @author Derek Hulley + */ +@AlfrescoPublicApi +public class RegexQNamePattern implements QNamePattern +{ + private static final Log logger = LogFactory.getLog(RegexQNamePattern.class); + + /** A helper pattern matcher that will match all qnames */ + public static final QNamePattern MATCH_ALL = new QNamePattern() + { + public boolean isMatch(QName qname) + { + return true; + } + + @Override + public boolean equals(Object obj) + { + // this is equal if the object's class is the same as this instances + if (obj == null) + { + return false; + } + else if (obj.getClass().equals(this.getClass())) + { + return true; + } + else + { + return false; + } + } + + }; + + private String namespaceUriPattern; + private String localNamePattern; + private String combinedPattern; + + /** + * @param namespaceUriPattern a regex pattern that will be applied to the namespace URI + * @param localNamePattern a regex pattern that will be applied to the local name + */ + public RegexQNamePattern(String namespaceUriPattern, String localNamePattern) + { + this.namespaceUriPattern = namespaceUriPattern; + this.localNamePattern = localNamePattern; + this.combinedPattern = null; + } + + /** + * @param combinedPattern a regex pattern that will be applied to the full qname + * string representation + * + * @see QName#toString() + */ + public RegexQNamePattern(String combinedPattern) + { + this.combinedPattern = combinedPattern; + this.namespaceUriPattern = null; + this.localNamePattern = null; + } + + public String toString() + { + StringBuilder sb = new StringBuilder(56); + sb.append("RegexQNamePattern["); + if (combinedPattern != null) + { + sb.append(" pattern=").append(combinedPattern); + } + else + { + sb.append(" uri=").append(namespaceUriPattern); + sb.append(", localname=").append(localNamePattern); + } + sb.append(" ]"); + return sb.toString(); + } + + /** + * @param qname the value to check against this pattern + * @return Returns true if the regex pattern provided match thos of the provided qname + */ + public boolean isMatch(QName qname) + { + boolean match = false; + if (combinedPattern != null) + { + String qnameStr = qname.toString(); + match = qnameStr.matches(combinedPattern); + } + else + { + match = (qname.getNamespaceURI().matches(namespaceUriPattern) && + qname.getLocalName().matches(localNamePattern)); + } + // done + if (logger.isDebugEnabled()) + { + logger.debug("QName matching: \n" + + " matcher: " + this + "\n" + + " qname: " + qname + "\n" + + " result: " + match); + } + return match; + } +} diff --git a/data-model/src/main/java/org/alfresco/util/BaseApplicationContextHelper.java b/data-model/src/main/java/org/alfresco/util/BaseApplicationContextHelper.java new file mode 100644 index 0000000000..1666a33e69 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/util/BaseApplicationContextHelper.java @@ -0,0 +1,337 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.LinkedList; +import java.util.List; +import java.util.NoSuchElementException; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.web.context.support.ServletContextResourcePatternResolver; + +/** + * Helper class to provide static and common access to the Spring + * {@link org.springframework.context.ApplicationContext application context}. + * + * @author Derek Hulley + */ +public abstract class BaseApplicationContextHelper +{ + private static ClassPathXmlApplicationContext instance; + private static String[] usedConfiguration; + private static String[] usedClassLocations; + private static boolean useLazyLoading = false; + private static boolean noAutoStart = false; + + public synchronized static ApplicationContext getApplicationContext(String[] configLocations) + { + if (configLocations == null) + { + throw new IllegalArgumentException("configLocations argument is mandatory."); + } + if (usedConfiguration != null && Arrays.deepEquals(configLocations, usedConfiguration)) + { + // The configuration was used to create the current context + return instance; + } + // The config has changed so close the current context (if any) + closeApplicationContext(); + + if(useLazyLoading || noAutoStart) { + instance = new VariableFeatureClassPathXmlApplicationContext(configLocations); + } else { + instance = new ClassPathXmlApplicationContext(configLocations); + } + + usedConfiguration = configLocations; + + return instance; + } + + /** + * Build a classloader for the given classLocations, using the thread's context class loader as its parent. + * + * @param classLocations String[] + * @return ClassLoader + * @throws IOException + */ + public static ClassLoader buildClassLoader(String[] classLocations) throws IOException + { + ResourceFinder resolver = new ResourceFinder(); + // Put the test directories at the front of the classpath + Resource[] resources = resolver.getResources(classLocations); + URL[] classpath = new URL[resources.length]; + for (int i = 0; i< resources.length; i++) + { + classpath[i] = resources[i].getURL(); + } + // Let's give our classloader 'child-first' resource loading qualities! + ClassLoader classLoader = new URLClassLoader(classpath, Thread.currentThread().getContextClassLoader()) + { + @Override + public URL getResource(String name) + { + URL ret = findResource(name); + return ret == null ? super.getResource(name) : ret; + } + + @SuppressWarnings("rawtypes") + @Override + public Enumeration getResources(String name) throws IOException + { + Enumeration[] tmp = new Enumeration[2]; + tmp[0] = findResources(name); + tmp[1] = super.getResources(name); + return new CompoundEnumeration(tmp); + } + }; + return classLoader; + } + + /** + * Provides a static, single instance of the application context. This method can be + * called repeatedly. + *

    + * If the configuration requested differs from one used previously, then the previously-created + * context is shut down. + * + * @return Returns an application context for the given configuration + */ + public synchronized static ApplicationContext getApplicationContext(String[] configLocations, String[] classLocations) throws IOException + { + if (configLocations == null) + { + throw new IllegalArgumentException("configLocations argument is mandatory."); + } + if (usedConfiguration != null && Arrays.deepEquals(configLocations, usedConfiguration) && classLocations != null && Arrays.deepEquals(classLocations, usedClassLocations)) + { + // The configuration was used to create the current context + return instance; + } + // The config has changed so close the current context (if any) + closeApplicationContext(); + + if(useLazyLoading || noAutoStart) { + instance = new VariableFeatureClassPathXmlApplicationContext(configLocations); + } else { + instance = new ClassPathXmlApplicationContext(configLocations, false); + } + + if(classLocations != null) + { + ClassLoader classLoader = buildClassLoader(classLocations); + instance.setClassLoader(classLoader); + } + + instance.refresh(); + + usedConfiguration = configLocations; + usedClassLocations = classLocations; + + return instance; + } + + /** + * Closes and releases the application context. On the next call to + * {@link #getApplicationContext(String[])} , a new context will be given. + */ + public static synchronized void closeApplicationContext() + { + if (instance == null) + { + // Nothing to do + return; + } + instance.close(); + instance = null; + usedConfiguration = null; + } + + /** + * Should the Spring beans be initilised in a lazy manner, or all in one go? + * Normally lazy loading/intialising shouldn't be used when running with the + * full context, but it may be appropriate to reduce startup times when + * using a small, cut down context. + */ + public static void setUseLazyLoading(boolean lazyLoading) + { + useLazyLoading = lazyLoading; + } + + /** + * Will the Spring beans be initilised in a lazy manner, or all in one go? + * The default it to load everything in one go, as spring normally does. + */ + public static boolean isUsingLazyLoading() + { + return useLazyLoading; + } + + /** + * Should the autoStart=true property on subsystems be honoured, or should + * this property be ignored and the auto start prevented? Normally we will + * use the spring configuration to decide what to start, but when running + * tests, you can use this to prevent the auto start. + */ + public static void setNoAutoStart(boolean noAutoStart) + { + BaseApplicationContextHelper.noAutoStart = noAutoStart; + } + + /** + * Will Subsystems with the autoStart=true property set on them be allowed + * to auto start? The default is to honour the spring configuration and + * allow them to, but they can be prevented if required. + */ + public static boolean isNoAutoStart() + { + return noAutoStart; + } + + /** + * Is there currently a context loaded and cached? + */ + public static boolean isContextLoaded() + { + return (instance != null); + } + + /** + * A wrapper around {@link ClassPathXmlApplicationContext} which allows us + * to enable lazy loading or prevent Subsystem autostart as requested. + */ + protected static class VariableFeatureClassPathXmlApplicationContext extends ClassPathXmlApplicationContext + { + protected VariableFeatureClassPathXmlApplicationContext(String[] configLocations) throws BeansException + { + super(configLocations); + } + + protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) + { + super.initBeanDefinitionReader(reader); + + if (useLazyLoading) + { + LazyClassPathXmlApplicationContext.postInitBeanDefinitionReader(reader); + } + if (noAutoStart) + { + NoAutoStartClassPathXmlApplicationContext.postInitBeanDefinitionReader(reader); + } + } + } + + /** + * Can be used in Spring configuration to search for all resources matching an array of patterns. + * + * @author dward + */ + public static class ResourceFinder extends ServletContextResourcePatternResolver + { + public ResourceFinder() + { + super(new DefaultResourceLoader()); + } + + /** + * The Constructor. + * + * @param resourceLoader + * the resource loader + */ + public ResourceFinder(ResourceLoader resourceLoader) + { + super(resourceLoader); + } + + /** + * Gets an array of resources matching the given location patterns. + * + * @param locationPatterns + * the location patterns + * @return the matching resources, ordered by locationPattern index and location in the classpath + * @throws IOException + * Signals that an I/O exception has occurred. + */ + public Resource[] getResources(String... locationPatterns) throws IOException + { + List resources = new LinkedList(); + for (String locationPattern : locationPatterns) + { + resources.addAll(Arrays.asList(getResources(locationPattern))); + } + Resource[] resourceArray = new Resource[resources.size()]; + resources.toArray(resourceArray); + return resourceArray; + } + } +} + +/* + * A utility class that will enumerate over an array of enumerations. + * was removed in version JDK 1.9 + */ +final class CompoundEnumeration implements Enumeration { + private final Enumeration[] enums; + private int index; + + public CompoundEnumeration(Enumeration[] enums) { + this.enums = enums; + } + + private boolean next() { + while (index < enums.length) { + if (enums[index] != null && enums[index].hasMoreElements()) { + return true; + } + index++; + } + return false; + } + + public boolean hasMoreElements() { + return next(); + } + + public E nextElement() { + if (!next()) { + throw new NoSuchElementException(); + } + return enums[index].nextElement(); + } +} diff --git a/data-model/src/main/java/org/alfresco/util/DataModelTestApplicationContextHelper.java b/data-model/src/main/java/org/alfresco/util/DataModelTestApplicationContextHelper.java new file mode 100644 index 0000000000..4891dbe5aa --- /dev/null +++ b/data-model/src/main/java/org/alfresco/util/DataModelTestApplicationContextHelper.java @@ -0,0 +1,52 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +import org.springframework.context.ApplicationContext; + +/** + * @author Andy + * + */ +public class DataModelTestApplicationContextHelper extends BaseApplicationContextHelper +{ + /** location of required configuration files */ + public static final String[] CONFIG_LOCATIONS = new String[] { "classpath:alfresco/data-model-stand-alone-context.xml" }; + + /** + * Provides a static, single instance of the default Alfresco application context. This method can be + * called repeatedly. + *

    + * If the configuration requested differs from one used previously, then the previously-created + * context is shut down. + * + * @return Returns an application context for the default Alfresco configuration + */ + public synchronized static ApplicationContext getApplicationContext() + { + return BaseApplicationContextHelper.getApplicationContext(CONFIG_LOCATIONS); + } +} diff --git a/data-model/src/main/java/org/alfresco/util/ISO9075.java b/data-model/src/main/java/org/alfresco/util/ISO9075.java new file mode 100644 index 0000000000..5a281e1d73 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/util/ISO9075.java @@ -0,0 +1,399 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +import java.util.Collection; + +import org.alfresco.api.AlfrescoPublicApi; +import org.alfresco.service.namespace.NamespaceException; +import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + +import org.apache.xerces.util.XMLChar; + +/** + * Support for the ISO 9075 encoding of XML element names. + * + * @author Andy Hind + */ +@AlfrescoPublicApi +public class ISO9075 +{ + /* + * Mask for hex encoding + */ + private static final int MASK = (1 << 4) - 1; + + /* + * Digits used string encoding + */ + private static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', + 'f' }; + + /** + * Private constructor + * + */ + private ISO9075() + { + super(); + } + + private static boolean isSQLNameStart(char c) + { + if('a' <= c && c <= 'z' ) + { + return true; + } + else if('A' <= c && c <= 'Z' ) + { + return true; + } + else if('_' == c) + { + return true; + } + else + { + return false; + } + } + + private static boolean isSQLName(char c) + { + if(isSQLNameStart(c)) + { + return true; + } + else if('0' <= c && c <= '9' ) + { + return true; + } + else if(':' == c) + { + return true; + } + else if('$' == c) + { + return true; + } + else if('#' == c) + { + return true; + } + else + { + return false; + } + } + + /** + * Encodes a SQL identifier + * + * Allowed at the start: 'a'..'z' | 'A'..'Z' | '_' + * Allowed after: 'a'..'z' | 'A'..'Z' | '0'..'9' | '_' | ':' | '$'| '#' + * + * @param toEncode String + * @return String + */ + public static String encodeSQL(String toEncode) + { + if ((toEncode == null) || (toEncode.length() == 0)) + { + return toEncode; + } + else + { + StringBuilder builder = new StringBuilder(toEncode.length()); + for (int i = 0; i < toEncode.length(); i++) + { + char c = toEncode.charAt(i); + // First requires special test + if (i == 0) + { + if (isSQLNameStart(c)) + { + // The first character may be the _ at the start of an + // encoding pattern + if (matchesEncodedPattern(toEncode, i)) + { + // Encode the first _ + encode('_', builder); + } + else + { + // Just append + builder.append(c); + } + } + else + { + // Encode an invalid start character for an XML element + // name. + encode(c, builder); + } + } + else if (!isSQLName(c)) + { + encode(c, builder); + } + else + { + if (matchesEncodedPattern(toEncode, i)) + { + // '_' must be encoded + encode('_', builder); + } + else + { + builder.append(c); + } + } + } + return builder.toString(); + } + + } + + + /** + * Encode a string according to ISO 9075 + * + * @param toEncode String + * @return String + */ + public static String encode(String toEncode) + { + if ((toEncode == null) || (toEncode.length() == 0)) + { + return toEncode; + } + else if (XMLChar.isValidName(toEncode) && (toEncode.indexOf("_x") == -1) && (toEncode.indexOf(':') == -1)) + { + return toEncode; + } + else + { + StringBuilder builder = new StringBuilder(toEncode.length()); + for (int i = 0; i < toEncode.length(); i++) + { + char c = toEncode.charAt(i); + // First requires special test + if (i == 0) + { + if (XMLChar.isNCNameStart(c)) + { + // The first character may be the _ at the start of an + // encoding pattern + if (matchesEncodedPattern(toEncode, i)) + { + // Encode the first _ + encode('_', builder); + } + else + { + // Just append + builder.append(c); + } + } + else + { + // Encode an invalid start character for an XML element + // name. + encode(c, builder); + } + } + else if (!XMLChar.isNCName(c)) + { + encode(c, builder); + } + else + { + if (matchesEncodedPattern(toEncode, i)) + { + // '_' must be encoded + encode('_', builder); + } + else + { + builder.append(c); + } + } + } + return builder.toString(); + } + + } + + private static boolean matchesEncodedPattern(String string, int position) + { + return (string.length() > position + 6) + && (string.charAt(position) == '_') && (string.charAt(position + 1) == 'x') + && isHexChar(string.charAt(position + 2)) && isHexChar(string.charAt(position + 3)) + && isHexChar(string.charAt(position + 4)) && isHexChar(string.charAt(position + 5)) + && (string.charAt(position + 6) == '_'); + } + + private static boolean isHexChar(char c) + { + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + return true; + default: + return false; + } + } + + public static String decode(String toDecode) + { + if ((toDecode == null) || (toDecode.length() < 7) || (toDecode.indexOf("_x") < 0)) + { + return toDecode; + } + StringBuffer decoded = new StringBuffer(); + for (int i = 0, l = toDecode.length(); i < l; i++) + { + if (matchesEncodedPattern(toDecode, i)) + { + decoded.append(((char) Integer.parseInt(toDecode.substring(i + 2, i + 6), 16))); + i += 6;// then one added for the loop to mkae the length of 7 + } + else + { + decoded.append(toDecode.charAt(i)); + } + } + return decoded.toString(); + } + + private static void encode(char c, StringBuilder builder) + { + char[] buf = new char[] { '_', 'x', '0', '0', '0', '0', '_' }; + int charPos = 6; + do + { + buf[--charPos] = DIGITS[c & MASK]; + c >>>= 4; + } + while (c != 0); + builder.append(buf); + } + + public static String getXPathName(QName qName, NamespacePrefixResolver nspr) + { + + Collection prefixes = nspr.getPrefixes(qName.getNamespaceURI()); + if (prefixes.size() == 0) + { + throw new NamespaceException("A namespace prefix is not registered for uri " + qName.getNamespaceURI()); + } + String prefix = prefixes.iterator().next(); + if (prefix.equals(NamespaceService.DEFAULT_PREFIX)) + { + return ISO9075.encode(qName.getLocalName()); + } + else + { + return prefix + ":" + ISO9075.encode(qName.getLocalName()); + } + + } + + public static String getXPathName(QName qName) + { + + return "{" + qName.getNamespaceURI() + "}" + ISO9075.encode(qName.getLocalName()); + + } + + public static QName parseXPathName(String str) + { + if(!str.startsWith("{")) + { + throw new IllegalArgumentException("Invalid xpath string " + str); + } + int idx = str.indexOf("}"); + if(idx == -1) + { + throw new IllegalArgumentException("Invalid xpath string " + str); + } + String namespaceURI = str.substring(1, idx); // skip opening brace + String localName = str.substring(idx+1); + return QName.createQName(namespaceURI, localName); + + } + + /** + * @param toLowerCaseEncoded String + * @return Object + */ + public static Object lowerCaseEncodedSQL(String toLowerCaseEncoded) + { + String lowerCased = toLowerCaseEncoded.toLowerCase(); + StringBuilder builder = new StringBuilder(toLowerCaseEncoded.length()); + for (int i = 0; i < toLowerCaseEncoded.length(); i++) + { + if (matchesEncodedPattern(toLowerCaseEncoded, i)) + { + for(int j = 0; j < 7; j++) + { + builder.append(lowerCased.charAt(i+j)); + } + i += 6; + + } + else + { + builder.append(toLowerCaseEncoded.charAt(i)); + } + + } + return builder.toString(); + } +} diff --git a/data-model/src/main/java/org/alfresco/util/LazyClassPathXmlApplicationContext.java b/data-model/src/main/java/org/alfresco/util/LazyClassPathXmlApplicationContext.java new file mode 100644 index 0000000000..d499f8fa27 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/util/LazyClassPathXmlApplicationContext.java @@ -0,0 +1,78 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate; +import org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.beans.factory.xml.XmlReaderContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.w3c.dom.Element; + +/** + * A wrapper around {@link ClassPathXmlApplicationContext} which forces + * all beans to be loaded lazily. + * You shouldn't do this in production, but it can be handy with + * unit tests, as it allows a quicker startup when you don't touch + * much of the application. + * + * @author Nick Burch + */ +public class LazyClassPathXmlApplicationContext extends + ClassPathXmlApplicationContext { + + public LazyClassPathXmlApplicationContext(String[] configLocations) + throws BeansException { + super(configLocations); + } + + protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) { + super.initBeanDefinitionReader(reader); + + postInitBeanDefinitionReader(reader); + } + + /** + * Does the work of enabling Lazy Init on the xml bean reader + */ + protected static void postInitBeanDefinitionReader(XmlBeanDefinitionReader reader) { + reader.setDocumentReaderClass(AlwaysLazyInitBeanDefinitionDocumentReader.class); + } + + protected static class AlwaysLazyInitBeanDefinitionDocumentReader extends DefaultBeanDefinitionDocumentReader + { + + @Override + protected BeanDefinitionParserDelegate createDelegate( + XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) + { + BeanDefinitionParserDelegate delegate = super.createDelegate(readerContext, root, parentDelegate); + delegate.getDefaults().setLazyInit("true"); + return delegate; + } + } +} diff --git a/data-model/src/main/java/org/alfresco/util/NoAutoStartClassPathXmlApplicationContext.java b/data-model/src/main/java/org/alfresco/util/NoAutoStartClassPathXmlApplicationContext.java new file mode 100644 index 0000000000..535ba610a8 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/util/NoAutoStartClassPathXmlApplicationContext.java @@ -0,0 +1,101 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate; +import org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.beans.factory.xml.XmlReaderContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.w3c.dom.Element; + +/** + * A wrapper around {@link ClassPathXmlApplicationContext} which + * stops Alfresco Subsystem (abstractPropertyBackedBean based) + * beans from being AutoStarted by tweaking their property definitions. + * You shouldn't do this in production, but it can be handy with + * unit tests, as it allows a quicker startup by preventing + * subsystems from starting up + * + * @author Nick Burch + */ +public class NoAutoStartClassPathXmlApplicationContext extends + ClassPathXmlApplicationContext { + + public NoAutoStartClassPathXmlApplicationContext(String[] configLocations) + throws BeansException { + super(configLocations); + } + + protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) { + super.initBeanDefinitionReader(reader); + + postInitBeanDefinitionReader(reader); + } + + /** + * Does the work of disabling the autostart of the + * Subsystem (abstractPropertyBackedBean) beans + * on the xml bean reader + */ + protected static void postInitBeanDefinitionReader(XmlBeanDefinitionReader reader) { + reader.setDocumentReaderClass(NoAutoStartBeanDefinitionDocumentReader.class); + } + + protected static class NoAutoStartBeanDefinitionDocumentReader extends DefaultBeanDefinitionDocumentReader + { + @Override + protected BeanDefinitionParserDelegate createDelegate( + XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) + { + BeanDefinitionParserDelegate delegate = new NoAutoStartBeanDefinitionParserDelegate(readerContext); + delegate.initDefaults(root); + return delegate; + } + } + + protected static class NoAutoStartBeanDefinitionParserDelegate extends BeanDefinitionParserDelegate { + protected NoAutoStartBeanDefinitionParserDelegate(XmlReaderContext readerContext) { + super(readerContext); + } + + @Override + public void parsePropertyElement(Element ele, BeanDefinition bd) { + String propertyName = ele.getAttribute("name"); + if("autoStart".equals(propertyName)) { + if("abstractPropertyBackedBean".equals(bd.getParentName())) { + String id = ele.getParentNode().getAttributes().getNamedItem("id").getTextContent(); + System.out.println("Preventing the autostart of Subsystem " + id); + return; + } + } + + super.parsePropertyElement(ele, bd); + } + } +} diff --git a/data-model/src/main/java/org/alfresco/util/NumericEncoder.java b/data-model/src/main/java/org/alfresco/util/NumericEncoder.java new file mode 100644 index 0000000000..113a3bca18 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/util/NumericEncoder.java @@ -0,0 +1,247 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +/** + * Support to encode numeric types in the lucene index. + * + * To support range queries in the lucene index numeric types need to be indexed + * specially. This has been addressed for int and long types for lucene and + * limited support (via scaling) for float and double. + * + * The implementation splits an int, long, float or double into the sign bit, + * optional exponent and mantissa either from the int or long format or its IEEE + * 754 byte representation. + * + * To index content so small negative numbers are indexed correctly and are + * after big negative numbers in range queries. + * + * The algorithm finds the sign, if the number is negative, then the mantissa + * and exponent are XORed against the appropriate masks. This reverses the + * order. As negative numbers appear first in the list their sign bit is 0 and + * positive numbers are 1. + * + * @author Andy Hind + */ +public class NumericEncoder +{ + /* + * Constants for integer encoding + */ + + static int INTEGER_SIGN_MASK = 0x80000000; + + /* + * Constants for long encoding + */ + + static long LONG_SIGN_MASK = 0x8000000000000000L; + + /* + * Constants for float encoding + */ + + static int FLOAT_SIGN_MASK = 0x80000000; + + static int FLOAT_EXPONENT_MASK = 0x7F800000; + + static int FLOAT_MANTISSA_MASK = 0x007FFFFF; + + /* + * Constants for double encoding + */ + + static long DOUBLE_SIGN_MASK = 0x8000000000000000L; + + static long DOUBLE_EXPONENT_MASK = 0x7FF0000000000000L; + + static long DOUBLE_MANTISSA_MASK = 0x000FFFFFFFFFFFFFL; + + private NumericEncoder() + { + super(); + } + + /** + * Encode an integer into a string that orders correctly using string + * comparison Integer.MIN_VALUE encodes as 00000000 and MAX_VALUE as + * ffffffff. + * + * @param intToEncode int + * @return the encoded string + */ + public static String encode(int intToEncode) + { + int replacement = intToEncode ^ INTEGER_SIGN_MASK; + return encodeToHex(replacement); + } + + /** + * Encode a long into a string that orders correctly using string comparison + * Long.MIN_VALUE encodes as 0000000000000000 and MAX_VALUE as + * ffffffffffffffff. + * + * @param longToEncode long + * @return - the encoded string + */ + public static String encode(long longToEncode) + { + long replacement = longToEncode ^ LONG_SIGN_MASK; + return encodeToHex(replacement); + } + + public static String encode(Long longToEncode) + { + if(longToEncode == null) + { + return encode(0L); + } + else + { + return encode(longToEncode.longValue()); + } + } + + /** + * Secode a long + * @param hex String + * @return - the decoded string + */ + public static long decodeLong(String hex) + { + return decodeFromHex(hex) ^ LONG_SIGN_MASK; + } + + + public static int decodeInt(String hex) + { + return decodeIntFromHex(hex) ^ INTEGER_SIGN_MASK; + } + + /** + * Encode a float into a string that orders correctly according to string + * comparison. Note that there is no negative NaN but there are codings that + * imply this. So NaN and -Infinity may not compare as expected. + * + * @param floatToEncode float + * @return - the encoded string + */ + public static String encode(float floatToEncode) + { + int bits = Float.floatToIntBits(floatToEncode); + int sign = bits & FLOAT_SIGN_MASK; + int exponent = bits & FLOAT_EXPONENT_MASK; + int mantissa = bits & FLOAT_MANTISSA_MASK; + if (sign != 0) + { + exponent ^= FLOAT_EXPONENT_MASK; + mantissa ^= FLOAT_MANTISSA_MASK; + } + sign ^= FLOAT_SIGN_MASK; + int replacement = sign | exponent | mantissa; + return encodeToHex(replacement); + } + + /** + * Encode a double into a string that orders correctly according to string + * comparison. Note that there is no negative NaN but there are codings that + * imply this. So NaN and -Infinity may not compare as expected. + * + * @param doubleToEncode double + * @return the encoded string + */ + public static String encode(double doubleToEncode) + { + long bits = Double.doubleToLongBits(doubleToEncode); + long sign = bits & DOUBLE_SIGN_MASK; + long exponent = bits & DOUBLE_EXPONENT_MASK; + long mantissa = bits & DOUBLE_MANTISSA_MASK; + if (sign != 0) + { + exponent ^= DOUBLE_EXPONENT_MASK; + mantissa ^= DOUBLE_MANTISSA_MASK; + } + sign ^= DOUBLE_SIGN_MASK; + long replacement = sign | exponent | mantissa; + return encodeToHex(replacement); + } + + private static String encodeToHex(int i) + { + char[] buf = new char[] { '0', '0', '0', '0', '0', '0', '0', '0' }; + int charPos = 8; + do + { + buf[--charPos] = DIGITS[i & MASK]; + i >>>= 4; + } + while (i != 0); + return new String(buf); + } + + private static String encodeToHex(long l) + { + char[] buf = new char[] { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0' }; + int charPos = 16; + do + { + buf[--charPos] = DIGITS[(int) l & MASK]; + l >>>= 4; + } + while (l != 0); + return new String(buf); + } + + private static long decodeFromHex(String hex) + { + long l = 0; + long factor = 1; + for(int i = 15; i >= 0; i--, factor <<= 4) + { + int digit = Character.digit(hex.charAt(i), 16); + l += digit*factor; + } + return l; + } + + private static int decodeIntFromHex(String hex) + { + int l = 0; + int factor = 1; + for(int i = 7; i >= 0; i--, factor <<= 4) + { + int digit = Character.digit(hex.charAt(i), 16); + l += digit*factor; + } + return l; + } + + + private static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', + 'f' }; + + private static final int MASK = (1 << 4) - 1; +} diff --git a/data-model/src/main/java/org/alfresco/util/SearchDateConversion.java b/data-model/src/main/java/org/alfresco/util/SearchDateConversion.java new file mode 100644 index 0000000000..c161da7071 --- /dev/null +++ b/data-model/src/main/java/org/alfresco/util/SearchDateConversion.java @@ -0,0 +1,178 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2017 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +import org.alfresco.service.cmr.search.IntervalSet; +import org.springframework.extensions.surf.util.I18NUtil; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +/** + * Moved from Solr4QueryParser + */ +public class SearchDateConversion +{ + + public static final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone("UTC"); + /** + * + * @param dateString + * @return Pair + */ + public static Pair parseDateString(String dateString) + { + try + { + Pair result = CachingDateFormat.lenientParse(dateString, Calendar.YEAR); + return result; + } catch (java.text.ParseException e) + { + SimpleDateFormat oldDf = CachingDateFormat.getDateFormat(); + try + { + Date date = oldDf.parse(dateString); + return new Pair(date, Calendar.SECOND); + } catch (java.text.ParseException ee) + { + if (dateString.equalsIgnoreCase("min")) + { + Calendar cal = Calendar.getInstance(I18NUtil.getLocale()); + cal.set(Calendar.YEAR, cal.getMinimum(Calendar.YEAR)); + cal.set(Calendar.DAY_OF_YEAR, cal.getMinimum(Calendar.DAY_OF_YEAR)); + cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY)); + cal.set(Calendar.MINUTE, cal.getMinimum(Calendar.MINUTE)); + cal.set(Calendar.SECOND, cal.getMinimum(Calendar.SECOND)); + cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND)); + return new Pair(cal.getTime(), Calendar.MILLISECOND); + } else if (dateString.equalsIgnoreCase("now")) + { + return new Pair(new Date(), Calendar.MILLISECOND); + } else if (dateString.equalsIgnoreCase("today")) + { + Calendar cal = Calendar.getInstance(I18NUtil.getLocale()); + cal.setTime(new Date()); + cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY)); + cal.set(Calendar.MINUTE, cal.getMinimum(Calendar.MINUTE)); + cal.set(Calendar.SECOND, cal.getMinimum(Calendar.SECOND)); + cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND)); + return new Pair(cal.getTime(), Calendar.DAY_OF_MONTH); + } else if (dateString.equalsIgnoreCase("max")) + { + Calendar cal = Calendar.getInstance(I18NUtil.getLocale()); + cal.set(Calendar.YEAR, cal.getMaximum(Calendar.YEAR)); + cal.set(Calendar.DAY_OF_YEAR, cal.getMaximum(Calendar.DAY_OF_YEAR)); + cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY)); + cal.set(Calendar.MINUTE, cal.getMaximum(Calendar.MINUTE)); + cal.set(Calendar.SECOND, cal.getMaximum(Calendar.SECOND)); + cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND)); + return new Pair(cal.getTime(), Calendar.MILLISECOND); + } else + { + return null; // delegate to SOLR date parsing + } + } + } + } + + /** + * @param dateAndResolution + * @return String date + */ + public static String getDateEnd(Pair dateAndResolution) + { + Calendar cal = Calendar.getInstance(I18NUtil.getLocale()); + cal.setTime(dateAndResolution.getFirst()); + switch (dateAndResolution.getSecond()) + { + case Calendar.YEAR: + cal.set(Calendar.MONTH, cal.getActualMaximum(Calendar.MONTH)); + case Calendar.MONTH: + cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH)); + case Calendar.DAY_OF_MONTH: + cal.set(Calendar.HOUR_OF_DAY, cal.getActualMaximum(Calendar.HOUR_OF_DAY)); + case Calendar.HOUR_OF_DAY: + cal.set(Calendar.MINUTE, cal.getActualMaximum(Calendar.MINUTE)); + case Calendar.MINUTE: + cal.set(Calendar.SECOND, cal.getActualMaximum(Calendar.SECOND)); + case Calendar.SECOND: + cal.set(Calendar.MILLISECOND, cal.getActualMaximum(Calendar.MILLISECOND)); + case Calendar.MILLISECOND: + default: + } + SimpleDateFormat formatter = CachingDateFormat.getSolrDatetimeFormat(); + formatter.setTimeZone(UTC_TIMEZONE); + return formatter.format(cal.getTime()); + } + + /** + * @param dateAndResolution + * @return String date + */ + public static String getDateStart(Pair dateAndResolution) + { + Calendar cal = Calendar.getInstance(I18NUtil.getLocale()); + cal.setTime(dateAndResolution.getFirst()); + switch (dateAndResolution.getSecond()) + { + case Calendar.YEAR: + cal.set(Calendar.MONTH, cal.getActualMinimum(Calendar.MONTH)); + case Calendar.MONTH: + cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH)); + case Calendar.DAY_OF_MONTH: + cal.set(Calendar.HOUR_OF_DAY, cal.getActualMinimum(Calendar.HOUR_OF_DAY)); + case Calendar.HOUR_OF_DAY: + cal.set(Calendar.MINUTE, cal.getActualMinimum(Calendar.MINUTE)); + case Calendar.MINUTE: + cal.set(Calendar.SECOND, cal.getActualMinimum(Calendar.SECOND)); + case Calendar.SECOND: + cal.set(Calendar.MILLISECOND, cal.getActualMinimum(Calendar.MILLISECOND)); + case Calendar.MILLISECOND: + default: + } + SimpleDateFormat formatter = CachingDateFormat.getSolrDatetimeFormat(); + formatter.setTimeZone(UTC_TIMEZONE); + return formatter.format(cal.getTime()); + } + + public static IntervalSet parseDateInterval(IntervalSet theSet, boolean isDate) + { + if (isDate) + { + Pair dateAndResolution1 = parseDateString(theSet.getStart()); + Pair dateAndResolution2 = parseDateString(theSet.getEnd()); + String start = dateAndResolution1 == null ? theSet.getStart() + : (theSet.isStartInclusive() ? getDateStart(dateAndResolution1) : getDateEnd(dateAndResolution1)); + String end = dateAndResolution2 == null ? theSet.getEnd() + : (theSet.isEndInclusive() ? getDateEnd(dateAndResolution2) : getDateStart(dateAndResolution2)); + return new IntervalSet(start, end, theSet.getLabel(), theSet.isStartInclusive(), theSet.isEndInclusive()); + + } + return theSet; + } +} diff --git a/data-model/src/main/java/org/alfresco/util/SearchLanguageConversion.java b/data-model/src/main/java/org/alfresco/util/SearchLanguageConversion.java new file mode 100644 index 0000000000..44d28971be --- /dev/null +++ b/data-model/src/main/java/org/alfresco/util/SearchLanguageConversion.java @@ -0,0 +1,395 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.springframework.util.StringUtils; + + +/** + * Helper class to provide conversions between different search languages + * + * @author Derek Hulley + */ +public class SearchLanguageConversion +{ + /** + * SQL like query language summary: + *

      + *
    • Escape: \
    • + *
    • Single char search: _
    • + *
    • Multiple char search: %
    • + *
    • Reserved: \%_
    • + *
    + */ + public static LanguageDefinition DEF_SQL_LIKE = new SimpleLanguageDef('\\', "%", "_", "\\%_[]"); + + /** + * XPath like query language summary: + *
      + *
    • Escape: \
    • + *
    • Single char search: _
    • + *
    • Multiple char search: %
    • + *
    • Reserved: \%_
    • + *
    + */ + public static LanguageDefinition DEF_XPATH_LIKE = new SimpleLanguageDef('\\', "%", "_", "\\%_[]"); + + /** + * Regular expression query language summary: + *
      + *
    • Escape: \
    • + *
    • Single char search: .
    • + *
    • Multiple char search: .*
    • + *
    • Reserved: \*.+?^$(){}[]|
    • + *
    + */ + public static LanguageDefinition DEF_REGEX = new SimpleLanguageDef('\\', ".*", ".", "\\*.+?^$(){}[]|"); + + /** + * Lucene syntax summary: Lucene Query Parser + */ + public static LanguageDefinition DEF_LUCENE = new LuceneLanguageDef(true); + + public static LanguageDefinition DEF_LUCENE_INTERNAL = new LuceneLanguageDef(false); + + /** + * CIFS name patch query language summary: + *
      + *
    • Escape: \ (but not used)
    • + *
    • Single char search: ?
    • + *
    • Multiple char search: *
    • + *
    • Reserved: "*\<>?/:|¬£%&+;
    • + *
    + */ + public static LanguageDefinition DEF_CIFS = new SimpleLanguageDef('\\', "*", "?", "\"*\\<>?/:|£%&+;"); + + /** + * Escape a string according to the XPath like function syntax. + * + * @param str + * the string to escape + * @return Returns the escaped string + */ + public static String escapeForXPathLike(String str) + { + return escape(DEF_XPATH_LIKE, str); + } + + /** + * Escape a string according to the regex language syntax. + * + * @param str + * the string to escape + * @return Returns the escaped string + */ + public static String escapeForRegex(String str) + { + return escape(DEF_REGEX, str); + } + + /** + * Escape a string according to the Lucene query syntax. + * + * @param str + * the string to escape + * @return Returns the escaped string + */ + public static String escapeForLucene(String str) + { + return escape(DEF_LUCENE, str); + } + + /** + * Generic escaping using the language definition + */ + private static String escape(LanguageDefinition def, String str) + { + StringBuilder sb = new StringBuilder(str.length() * 2); + + char[] chars = str.toCharArray(); + for (int i = 0; i < chars.length; i++) + { + // first check for reserved chars + if (def.isReserved(chars[i])) + { + // escape it + sb.append(def.escapeChar); + } + sb.append(chars[i]); + } + return sb.toString(); + } + + /** + * Convert an xpath like function clause into a regex query. + * + * @param xpathLikeClause String + * @return Returns a valid regular expression that is equivalent to the given xpath like clause. + */ + public static String convertXPathLikeToRegex(String xpathLikeClause) + { + return "(?s)" + convert(DEF_XPATH_LIKE, DEF_REGEX, xpathLikeClause); + } + + /** + * Convert an xpath like function clause into a Lucene query. + * + * @param xpathLikeClause String + * @return Returns a valid Lucene expression that is equivalent to the given xpath like clause. + */ + public static String convertXPathLikeToLucene(String xpathLikeClause) + { + return convert(DEF_XPATH_LIKE, DEF_LUCENE, xpathLikeClause); + } + + /** + * Convert a sql like function clause into a Lucene query. + * + * @param sqlLikeClause String + * @return Returns a valid Lucene expression that is equivalent to the given sql like clause. + */ + public static String convertSQLLikeToLucene(String sqlLikeClause) + { + return convert(DEF_SQL_LIKE, DEF_LUCENE_INTERNAL, sqlLikeClause); + } + + /** + * Convert a sql like function clause into a regex query. + * + * @param sqlLikeClause String + * @return Returns a valid regular expression that is equivalent to the given sql like clause. + */ + public static String convertSQLLikeToRegex(String sqlLikeClause) + { + return "(?s)" + convert(DEF_SQL_LIKE, DEF_REGEX, sqlLikeClause); + } + + /** + * Convert a CIFS name path into the equivalent Lucene query. + * + * @param cifsNamePath + * the CIFS named path + * @return Returns a valid Lucene expression that is equivalent to the given CIFS name path + */ + public static String convertCifsToLucene(String cifsNamePath) + { + return convert(DEF_CIFS, DEF_LUCENE, cifsNamePath); + } + + public static String convert(LanguageDefinition from, LanguageDefinition to, String query) + { + char[] chars = query.toCharArray(); + + StringBuilder sb = new StringBuilder(chars.length * 2); + + boolean escaping = false; + + for (int i = 0; i < chars.length; i++) + { + if (escaping) // if we are currently escaping, just escape the current character + { + if(to.isReserved(chars[i])) + { + sb.append(to.escapeChar); // the to format escape char + } + sb.append(chars[i]); // the current char + escaping = false; + } + else if (chars[i] == from.escapeChar) // not escaping and have escape char + { + escaping = true; + } + else if (query.startsWith(from.multiCharWildcard, i)) // not escaping but have multi-char wildcard + { + // translate the wildcard + sb.append(to.multiCharWildcard); + } + else if (query.startsWith(from.singleCharWildcard, i)) // have single-char wildcard + { + // translate the wildcard + sb.append(to.singleCharWildcard); + } + else if (to.isReserved(chars[i])) // reserved character + { + sb.append(to.escapeChar).append(chars[i]); + } + else + // just a normal char in both + { + sb.append(chars[i]); + } + } + return sb.toString(); + } + + /** + * Simple store of special characters for a given query language + */ + public static abstract class LanguageDefinition + { + public final char escapeChar; + + public final String multiCharWildcard; + + public final String singleCharWildcard; + + public LanguageDefinition(char escapeChar, String multiCharWildcard, String singleCharWildcard) + { + this.escapeChar = escapeChar; + this.multiCharWildcard = multiCharWildcard; + this.singleCharWildcard = singleCharWildcard; + } + + public abstract boolean isReserved(char ch); + } + + private static class SimpleLanguageDef extends LanguageDefinition + { + private String reserved; + + public SimpleLanguageDef(char escapeChar, String multiCharWildcard, String singleCharWildcard, String reserved) + { + super(escapeChar, multiCharWildcard, singleCharWildcard); + this.reserved = reserved; + } + + @Override + public boolean isReserved(char ch) + { + return (reserved.indexOf(ch) > -1); + } + } + + private static class LuceneLanguageDef extends LanguageDefinition + { + private String reserved; + + public LuceneLanguageDef(boolean reserve) + { + super('\\', "*", "?"); + if (reserve) + { + init(); + } + else + { + reserved = ""; + } + } + + /** + * Discovers all the reserved chars + */ + private void init() + { + StringBuilder sb = new StringBuilder(20); + for (char ch = 0; ch < 256; ch++) + { + char[] chars = new char[] { ch }; + String unescaped = new String(chars); + // check it + String escaped = SearchLanguageConversion.escapeLuceneQuery(unescaped); + if (!escaped.equals(unescaped)) + { + // it was escaped + sb.append(ch); + } + } + reserved = sb.toString(); + } + + @Override + public boolean isReserved(char ch) + { + return (reserved.indexOf(ch) > -1); + } + } + + /** + * We have to escape lucene query strings outside of lucene - as we do not depend on any given version of lucene + * The escaping here is taken from lucene 4.9.0 + * + * The reserved (and escaped characters) are: + * + * \ + - ! ( ) : ^ [ ] " { } ~ * ? | & / + * + * The escape character is \ + * + * @param query String + * @return - the escaped query string + */ + public static String escapeLuceneQuery(String query) + { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < query.length(); i++) { + char c = query.charAt(i); + // These characters are part of the query syntax and must be escaped + if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':' + || c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c == '~' + || c == '*' || c == '?' || c == '|' || c == '&' || c == '/') { + sb.append('\\'); + } + sb.append(c); + } + return sb.toString(); + } + + public static String[] tokenizeString(String query) + { + String trimmed = StringUtils.trimWhitespace(query); + if (trimmed == null || trimmed.length() < 1) return new String[]{query}; + List split = new ArrayList(); + + char[] toSplit = trimmed.toCharArray(); + StringBuffer buff = new StringBuffer(); + + for (char c : toSplit) { + if (Character.isWhitespace(c)) + { + if (buff.length() > 0) + { + split.add(buff.toString()); + buff = new StringBuffer(); + } + } + else + { + buff.append(c); + } + } + + if (buff.length() > 0) + { + split.add(buff.toString()); + } + + return split.toArray(new String[split.size()]); + } +} diff --git a/data-model/src/main/java/org/alfresco/util/WebApplicationContextLoader.java b/data-model/src/main/java/org/alfresco/util/WebApplicationContextLoader.java new file mode 100644 index 0000000000..ff882adb3a --- /dev/null +++ b/data-model/src/main/java/org/alfresco/util/WebApplicationContextLoader.java @@ -0,0 +1,143 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +import java.io.IOException; + +import javax.servlet.ServletContext; + +import org.apache.chemistry.opencmis.commons.server.CmisServiceFactory; +import org.apache.chemistry.opencmis.server.impl.CmisRepositoryContextListener; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.web.context.support.GenericWebApplicationContext; + +public class WebApplicationContextLoader +{ + private static ConfigurableApplicationContext instance; + private static boolean useLazyLoading = false; + private static boolean noAutoStart = false; + + /** + * Provides a static, single instance of the application context. This method can be + * called repeatedly. + *

    + * If the configuration requested differs from one used previously, then the previously-created + * context is shut down. + * + * @return Returns an application context for the given configuration + */ + public synchronized static ConfigurableApplicationContext getApplicationContext(ServletContext servletContext, String[] configLocations) + { + AbstractApplicationContext ctx = (AbstractApplicationContext)BaseApplicationContextHelper.getApplicationContext(configLocations); + + CmisServiceFactory factory = (CmisServiceFactory)ctx.getBean("CMISServiceFactory"); + + DefaultListableBeanFactory dlbf = new DefaultListableBeanFactory(ctx.getBeanFactory()); + GenericWebApplicationContext gwac = new GenericWebApplicationContext(dlbf); + servletContext.setAttribute(GenericWebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, gwac); + servletContext.setAttribute(CmisRepositoryContextListener.SERVICES_FACTORY, factory); + gwac.setServletContext(servletContext); + gwac.refresh(); + + return gwac; + } + + public synchronized static ConfigurableApplicationContext getApplicationContext(ServletContext servletContext, final String[] configLocations, + final String[] classLocations) throws IOException + { + final AbstractApplicationContext ctx = (AbstractApplicationContext)BaseApplicationContextHelper.getApplicationContext(configLocations, classLocations); + DefaultListableBeanFactory dlbf = new DefaultListableBeanFactory(ctx.getBeanFactory()); + GenericWebApplicationContext gwac = new GenericWebApplicationContext(dlbf); + CmisServiceFactory factory = (CmisServiceFactory)ctx.getBean("CMISServiceFactory"); + + servletContext.setAttribute(GenericWebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, gwac); + servletContext.setAttribute(CmisRepositoryContextListener.SERVICES_FACTORY, factory); + gwac.setServletContext(servletContext); + gwac.refresh(); + + return gwac; + } + + /** + * Should the Spring beans be initilised in a lazy manner, or all in one go? + * Normally lazy loading/intialising shouldn't be used when running with the + * full context, but it may be appropriate to reduce startup times when + * using a small, cut down context. + */ + public static void setUseLazyLoading(boolean lazyLoading) + { + useLazyLoading = lazyLoading; + } + + /** + * Will the Spring beans be initilised in a lazy manner, or all in one go? + * The default it to load everything in one go, as spring normally does. + */ + public static boolean isUsingLazyLoading() + { + return useLazyLoading; + } + + /** + * Should the autoStart=true property on subsystems be honoured, or should + * this property be ignored and the auto start prevented? Normally we will + * use the spring configuration to decide what to start, but when running + * tests, you can use this to prevent the auto start. + */ + public static void setNoAutoStart(boolean noAutoStart) + { + WebApplicationContextLoader.noAutoStart = noAutoStart; + } + + /** + * Will Subsystems with the autoStart=true property set on them be allowed + * to auto start? The default is to honour the spring configuration and + * allow them to, but they can be prevented if required. + */ + public static boolean isNoAutoStart() + { + return noAutoStart; + } + + /** + * Is there currently a context loaded and cached? + */ + public static boolean isContextLoaded() + { + return (instance != null); + } + + protected static class WebApplicationContext extends GenericWebApplicationContext + { + protected WebApplicationContext(ServletContext servletContext, AbstractApplicationContext ctx) throws BeansException + { + super((DefaultListableBeanFactory)ctx.getBeanFactory(), servletContext); + } + } +} diff --git a/data-model/src/main/java/org/apache/tika/mime/custom-mimetypes.xml b/data-model/src/main/java/org/apache/tika/mime/custom-mimetypes.xml new file mode 100644 index 0000000000..4b3df3f6f3 --- /dev/null +++ b/data-model/src/main/java/org/apache/tika/mime/custom-mimetypes.xml @@ -0,0 +1,28 @@ + + + + + + + <_comment>Alfresco Content Package + + + + diff --git a/data-model/src/main/resources/alfresco/data-model-stand-alone-context.xml b/data-model/src/main/resources/alfresco/data-model-stand-alone-context.xml new file mode 100644 index 0000000000..9ad98258a3 --- /dev/null +++ b/data-model/src/main/resources/alfresco/data-model-stand-alone-context.xml @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + alfresco.messages.dictionary-messages + + + + + + + + + + + + + + + + + + + + + + + + ${lucene.defaultAnalyserResourceBundleName} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + alfresco/model/dictionaryModel.xml + + + + + alfresco/messages/dictionary-model + + + + + + + + + + UTF-8 + + + + + + + + + + + + + + + + + + + + + + + + + + + classpath:alfresco/mimetype/mimetype-map.xml + classpath:alfresco/mimetype/mimetype-map-openoffice.xml + + + + + + + + + + + + + + alfresco/model/cmisModel.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data-model/src/main/resources/alfresco/messages/dictionary-messages.properties b/data-model/src/main/resources/alfresco/messages/dictionary-messages.properties new file mode 100644 index 0000000000..929016b506 --- /dev/null +++ b/data-model/src/main/resources/alfresco/messages/dictionary-messages.properties @@ -0,0 +1,90 @@ +# Dictionary-related messages + +d_dictionary.model.err.no_model=Model ''{0}'' does not exist +d_dictionary.model.err.type_not_found=Failed to create anonymous type as specified type {0} not found +d_dictionary.model.err.aspect_not_found=Failed to create anonymous type as specified aspect {0} not found +d_dictionary.model.err.duplicate_constraint_on_model=Found duplicate constraint definition ''{0}'' within model ''{1}'' +d_dictionary.model.err.parse.failure=Failed to parse model +d_dictionary.model.err.create_m2model.failure=Failed to create M2 Model + +d_dictionary.constraint.err.cyclic_ref=Constraint ''{0}'' is part of a cyclic reference of constraints +d_dictionary.constraint.err.type_and_ref=Constraint ''{0}'' cannot have a ''type'' and be a ''reference'' attribute +d_dictionary.constraint.err.type_or_ref=Constraint ''{0}'' must have either a ''type'' or a ''reference'' attribute +d_dictionary.constraint.err.ref_not_found=Constraint reference ''{0}'' not found on constraint ''{1}'' +d_dictionary.constraint.err.anon_needs_property=Anonymous constraints can only be declared within the context of a property +d_dictionary.constraint.err.invalid_type=Constraint type ''{0}'' on constraint ''{1}'' is not a well-known type or a valid Constraint implementation +d_dictionary.constraint.err.property_simple_and_list=Constraint ''{0}'' has both a simple and list value for property ''{1}'' +d_dictionary.constraint.err.construct_failure=Failed to construct an instance of type ''{0}'' for constraint ''{1}'' +d_dictionary.constraint.err.property_mismatch=Property mismatch setting property ''{0}'' on constraint ''{1}'' +d_dictionary.constraint.err.reserved_property=Property ''{0}'' is reserved and can''t be set on constraint ''{1}''. +d_dictionary.constraint.err.property_not_set=Property ''{0}'' has not been set on constraint ''{1}'' +d_dictionary.constraint.err.evaluate_exception=Exception during evaluation of constraint ''{0}'': {1} +d_dictionary.constraint.err.namespace_not_defined=Cannot define constraint ''{0}'' as namespace ''{1}'' is not defined by model ''{2}'' + +d_dictionary.property.err.property_type_not_specified=Property type of property ''{0}'' must be specified +d_dictionary.property.err.property_type_not_found=Property type ''{0}'' of property ''{1}'' is not found +d_dictionary.property.err.single_valued_content=Content properties must be single-valued +d_dictionary.property.err.duplicate_constraint_on_property=Found duplicate constraint definition ''{0}'' within property ''{1}'' +d_dictionary.property.err.cannot_relax_mandatory=Cannot relax mandatory attribute of property ''{0} +d_dictionary.property.err.cannot_relax_mandatory_enforcement=Cannot relax mandatory attribute enforcement of property ''{0} + +d_dictionary.constraint.registered.not_registered=There is no constraint registered by name ''{0}''. + +d_dictionary.constraint.regex.no_match=Value ''{0}'' does not match regular expression: {1} +d_dictionary.constraint.regex.match=Value ''{0}'' matches regular expression: {1} +d_dictionary.constraint.regex.error.cm\:filename=Value ''{0}'' is not valid as a file name. This property must be a valid file name. + +d_dictionary.constraint.numeric_range.invalid_min_value=Invalid ''minValue'' property: {0} +d_dictionary.constraint.numeric_range.invalid_max_value=Invalid ''maxValue'' property: {0} +d_dictionary.constraint.numeric_range.non_numeric=Property value could not be converted to a double: {0} +d_dictionary.constraint.numeric_range.out_of_range=Numeric value ''{0}'' is not in range [{1}; {2}] + +d_dictionary.constraint.string_length.invalid_min_length=Invalid ''minLength'' property: {0} +d_dictionary.constraint.string_length.invalid_max_length=Invalid ''maxLength'' property: {0} +d_dictionary.constraint.string_length.non_string=Property value could not be converted to a String: {0} +d_dictionary.constraint.string_length.invalid_length=String length of ''{0}'' is not in range [{1}; {2}] + +d_dictionary.constraint.list_of_values.no_values=The list of allowed values is empty +d_dictionary.constraint.list_of_values.non_string=Property value could not be converted to a String: {0} +d_dictionary.constraint.list_of_values.invalid_value=The value is not an allowed value: {0} + +d_dictionary.constraint.user_name.invalid_user_name=The value ''{0}'' is not an allowed user name: it is an authority of type: {1} +d_dictionary.constraint.user_name.non_string=Property value could not be converted to a String: {0} + +d_dictionary.constraint.authority_name.invalid_authority_name=The value ''{0}'' is not an allowed authority name: it is an authority of type: {1} +d_dictionary.constraint.authority_name.non_string=Property value could not be converted to a String: {0} + +d_dictionary.model_diff.element_type.unknown=Unknown element type ''{0}'' +d_dictionary.model_diff.diff_type.unknown=Unknown diff type ''{0}'' + +d_dictionary.compiled_model.err.compile.failure=Failed to compile model ''{0}'' +d_dictionary.compiled_model.err.duplicate_property_type=Found duplicate property type definition ''{0}'' +d_dictionary.compiled_model.err.duplicate_type=Found duplicate ''class'' definition. The ''type'' name ''{0}'' is already in use as a ''type'' or ''aspect'' name +d_dictionary.compiled_model.err.duplicate_aspect=Found duplicate ''class'' definition. The ''aspect'' name ''{0}'' is already in use as a ''type'' or ''aspect'' name +d_dictionary.compiled_model.err.duplicate_constraint=Found duplicate constraint definition ''{0}'' +d_dictionary.compiled_model.err.cyclic_ref=Class ''{0}'' is a part of a cyclic reference within model ''{1}'' + +d_dictionary.association.target_class_not_specified=Target class of association ''{0}'' must be specified +d_dictionary.association.target_class_not_found=Target class ''{0}'' of association ''{1}'' is not found + +d_dictionary.class_definition.class.namespace_not_defined=Cannot define class ''{0}'' as namespace ''{1}'' is not defined by model ''{2}'' +d_dictionary.class_definition.class.parent_not_found=Parent class ''{0}'' of class ''{1}'' is not found +d_dictionary.class_definition.property.namespace_not_defined=Cannot define property ''{0}'' as namespace ''{1}'' is not defined by model ''{2}'' +d_dictionary.class_definition.property_not_exist=Class ''{0}'' attempting to override property ''{1}'' which does not exist +d_dictionary.class_definition.association.namespace_not_defined=Cannot define association ''{0}'' as namespace ''{1}'' is not defined by model ''{2}'' +d_dictionary.class_definition.duplicate.property_definition=Found duplicate property definition ''{0}'' within class ''{1}'' +d_dictionary.class_definition.duplicate.property_existing_def=Found duplicate property definition ''{0}'' within class ''{1}'' and class ''{2}'' +d_dictionary.class_definition.duplicate.property_and_property_override=Found duplicate property and property override definition ''{0}'' within class ''{1}'' +d_dictionary.class_definition.duplicate.property_override_definition=Found duplicate property override definition ''{0}'' within class ''{1}'' +d_dictionary.class_definition.duplicate.association_definition=Found duplicate association definition ''{0}'' within class ''{1}'' +d_dictionary.class_definition.duplicate.association_existing_def=Found duplicate association definition ''{0}'' within class ''{1}'' and class ''{2}'' +d_dictionary.class_definition.duplicate.property_in_class_hierarchy=Duplicate property definition ''{0}'' found in class hierarchy of ''{1}'' +d_dictionary.class_definition.duplicate.association_in_class_hierarchy=Duplicate association definition ''{0}'' found in class hierarchy of ''{1}'' +d_dictionary.class_definition.mandatory_aspect_not_found=Mandatory aspect ''{0}'' of class ''{1}'' is not found + +d_dictionary.bootstrap.model_not_found=Could not find bootstrap model ''{0}'' +d_dictionary.bootstrap.model_not_imported=Could not import bootstrap model ''{0}'' + +d_dictionary.data_type.namespace_not_defined=Cannot define data type ''{0}'' as namespace ''{1}'' is not defined by model ''{2}'' +d_dictionary.data_type.java_class_not_specified=Java class of data type ''{0}'' must be specified +d_dictionary.data_type.java_class_invalid=Java class ''{0}'' of data type ''{1}'' is invalid \ No newline at end of file diff --git a/data-model/src/main/resources/alfresco/messages/dictionary-model.properties b/data-model/src/main/resources/alfresco/messages/dictionary-model.properties new file mode 100644 index 0000000000..f9ceae5b4e --- /dev/null +++ b/data-model/src/main/resources/alfresco/messages/dictionary-model.properties @@ -0,0 +1,34 @@ +# Display labels for Dictionary Model + +d_dictionary.description=Alfresco Dictionary Model + +d_dictionary.datatype.d_any.title=Any +d_dictionary.datatype.d_any.description=Any +d_dictionary.datatype.d_text.title=Text +d_dictionary.datatype.d_text.description=Text +d_dictionary.datatype.d_content.title=Content +d_dictionary.datatype.d_content.description=Content +d_dictionary.datatype.d_int.title=Integer +d_dictionary.datatype.d_int.description=Integer +d_dictionary.datatype.d_long.title=Long +d_dictionary.datatype.d_long.description=Long +d_dictionary.datatype.d_float.title=Float +d_dictionary.datatype.d_float.description=Float +d_dictionary.datatype.d_double.title=Double +d_dictionary.datatype.d_double.description=Double +d_dictionary.datatype.d_date.title=Date +d_dictionary.datatype.d_date.description=Date +d_dictionary.datatype.d_datetime.title=Date and Time +d_dictionary.datatype.d_datetime.description=Date and Time +d_dictionary.datatype.d_boolean.title=Boolean +d_dictionary.datatype.d_boolean.description=Boolean +d_dictionary.datatype.d_qname.title=Qualified Name +d_dictionary.datatype.d_qname.description=Qualified Name +d_dictionary.datatype.d_guid.title=Unique Identifier +d_dictionary.datatype.d_guid.description=Unique Identifier +d_dictionary.datatype.d_category.title=Category +d_dictionary.datatype.d_category.description=Category +d_dictionary.datatype.d_noderef.title=Reference +d_dictionary.datatype.d_noderef.description=Reference +d_dictionary.datatype.d_path.title=Path +d_dictionary.datatype.d_path.description=Path diff --git a/data-model/src/main/resources/alfresco/messages/dictionary-model_de.properties b/data-model/src/main/resources/alfresco/messages/dictionary-model_de.properties new file mode 100755 index 0000000000..c5c50f03c5 --- /dev/null +++ b/data-model/src/main/resources/alfresco/messages/dictionary-model_de.properties @@ -0,0 +1,34 @@ +# Display labels for Dictionary Model + +d_dictionary.description=Modell f\u00fcr Alfresco W\u00f6rterbuch + +d_dictionary.datatype.d_any.title=Jede +d_dictionary.datatype.d_any.description=Jede +d_dictionary.datatype.d_text.title=Text +d_dictionary.datatype.d_text.description=Text +d_dictionary.datatype.d_content.title=Inhalt +d_dictionary.datatype.d_content.description=Inhalt +d_dictionary.datatype.d_int.title=Integer +d_dictionary.datatype.d_int.description=Integer +d_dictionary.datatype.d_long.title=Long +d_dictionary.datatype.d_long.description=Long +d_dictionary.datatype.d_float.title=Float +d_dictionary.datatype.d_float.description=Float +d_dictionary.datatype.d_double.title=Double +d_dictionary.datatype.d_double.description=Double +d_dictionary.datatype.d_date.title=Datum +d_dictionary.datatype.d_date.description=Datum +d_dictionary.datatype.d_datetime.title=Datum und Uhrzeit +d_dictionary.datatype.d_datetime.description=Datum und Uhrzeit +d_dictionary.datatype.d_boolean.title=Boolesch +d_dictionary.datatype.d_boolean.description=Boolesch +d_dictionary.datatype.d_qname.title=Qualifizierter Name +d_dictionary.datatype.d_qname.description=Qualifizierter Name +d_dictionary.datatype.d_guid.title=Eindeutiger Identifikator +d_dictionary.datatype.d_guid.description=Eindeutiger Identifikator +d_dictionary.datatype.d_category.title=Kategorie +d_dictionary.datatype.d_category.description=Kategorie +d_dictionary.datatype.d_noderef.title=Referenz +d_dictionary.datatype.d_noderef.description=Referenz +d_dictionary.datatype.d_path.title=Pfad +d_dictionary.datatype.d_path.description=Pfad diff --git a/data-model/src/main/resources/alfresco/messages/dictionary-model_es.properties b/data-model/src/main/resources/alfresco/messages/dictionary-model_es.properties new file mode 100755 index 0000000000..075d713a83 --- /dev/null +++ b/data-model/src/main/resources/alfresco/messages/dictionary-model_es.properties @@ -0,0 +1,34 @@ +# Display labels for Dictionary Model + +d_dictionary.description=Modelo de diccionario Alfresco + +d_dictionary.datatype.d_any.title=Cualquiera +d_dictionary.datatype.d_any.description=Cualquiera +d_dictionary.datatype.d_text.title=Texto +d_dictionary.datatype.d_text.description=Texto +d_dictionary.datatype.d_content.title=Contenido +d_dictionary.datatype.d_content.description=Contenido +d_dictionary.datatype.d_int.title=Entero +d_dictionary.datatype.d_int.description=Entero +d_dictionary.datatype.d_long.title=Entero largo +d_dictionary.datatype.d_long.description=Entero largo +d_dictionary.datatype.d_float.title=Coma flotante +d_dictionary.datatype.d_float.description=Coma flotante +d_dictionary.datatype.d_double.title=Doble precisi\u00f3n +d_dictionary.datatype.d_double.description=Doble precisi\u00f3n +d_dictionary.datatype.d_date.title=Fecha +d_dictionary.datatype.d_date.description=Fecha +d_dictionary.datatype.d_datetime.title=Fecha y hora +d_dictionary.datatype.d_datetime.description=Fecha y hora +d_dictionary.datatype.d_boolean.title=Booleano +d_dictionary.datatype.d_boolean.description=Booleano +d_dictionary.datatype.d_qname.title=Nombre cualificado +d_dictionary.datatype.d_qname.description=Nombre cualificado +d_dictionary.datatype.d_guid.title=Identificador \u00fanico +d_dictionary.datatype.d_guid.description=Identificador \u00fanico +d_dictionary.datatype.d_category.title=Categor\u00eda +d_dictionary.datatype.d_category.description=Categor\u00eda +d_dictionary.datatype.d_noderef.title=Referencia +d_dictionary.datatype.d_noderef.description=Referencia +d_dictionary.datatype.d_path.title=Ruta +d_dictionary.datatype.d_path.description=Ruta diff --git a/data-model/src/main/resources/alfresco/messages/dictionary-model_fr.properties b/data-model/src/main/resources/alfresco/messages/dictionary-model_fr.properties new file mode 100755 index 0000000000..f143b99c2f --- /dev/null +++ b/data-model/src/main/resources/alfresco/messages/dictionary-model_fr.properties @@ -0,0 +1,34 @@ +# Display labels for Dictionary Model + +d_dictionary.description=Mod\u00e8le de dictionnaire Alfresco + +d_dictionary.datatype.d_any.title=Tout +d_dictionary.datatype.d_any.description=Tout +d_dictionary.datatype.d_text.title=Texte +d_dictionary.datatype.d_text.description=Texte +d_dictionary.datatype.d_content.title=Contenu +d_dictionary.datatype.d_content.description=Contenu +d_dictionary.datatype.d_int.title=Nombre entier +d_dictionary.datatype.d_int.description=Nombre entier +d_dictionary.datatype.d_long.title=Nombre Long +d_dictionary.datatype.d_long.description=Nombre Long +d_dictionary.datatype.d_float.title=Nombre d\u00e9cimal +d_dictionary.datatype.d_float.description=Nombre d\u00e9cimal +d_dictionary.datatype.d_double.title=Nombre Double +d_dictionary.datatype.d_double.description=Nombre Double +d_dictionary.datatype.d_date.title=Date +d_dictionary.datatype.d_date.description=Date +d_dictionary.datatype.d_datetime.title=Date et heure +d_dictionary.datatype.d_datetime.description=Date et heure +d_dictionary.datatype.d_boolean.title=Bool\u00e9en +d_dictionary.datatype.d_boolean.description=Bool\u00e9en +d_dictionary.datatype.d_qname.title=Nom Qualifi\u00e9 +d_dictionary.datatype.d_qname.description=Nom Qualifi\u00e9 +d_dictionary.datatype.d_guid.title=Identifiant Unique +d_dictionary.datatype.d_guid.description=Identifiant Unique +d_dictionary.datatype.d_category.title=Cat\u00e9gorie +d_dictionary.datatype.d_category.description=Cat\u00e9gorie +d_dictionary.datatype.d_noderef.title=R\u00e9f\u00e9rence +d_dictionary.datatype.d_noderef.description=R\u00e9f\u00e9rence +d_dictionary.datatype.d_path.title=Chemin +d_dictionary.datatype.d_path.description=Chemin diff --git a/data-model/src/main/resources/alfresco/messages/dictionary-model_it.properties b/data-model/src/main/resources/alfresco/messages/dictionary-model_it.properties new file mode 100755 index 0000000000..a27c70302b --- /dev/null +++ b/data-model/src/main/resources/alfresco/messages/dictionary-model_it.properties @@ -0,0 +1,34 @@ +# Display labels for Dictionary Model + +d_dictionary.description=Modello di dizionario Alfresco + +d_dictionary.datatype.d_any.title=Qualsiasi +d_dictionary.datatype.d_any.description=Qualsiasi +d_dictionary.datatype.d_text.title=Testo +d_dictionary.datatype.d_text.description=Testo +d_dictionary.datatype.d_content.title=Contenuto +d_dictionary.datatype.d_content.description=Contenuto +d_dictionary.datatype.d_int.title=Intero +d_dictionary.datatype.d_int.description=Intero +d_dictionary.datatype.d_long.title=Long +d_dictionary.datatype.d_long.description=Long +d_dictionary.datatype.d_float.title=Float +d_dictionary.datatype.d_float.description=Float +d_dictionary.datatype.d_double.title=Double +d_dictionary.datatype.d_double.description=Double +d_dictionary.datatype.d_date.title=Data +d_dictionary.datatype.d_date.description=Data +d_dictionary.datatype.d_datetime.title=Data e ora +d_dictionary.datatype.d_datetime.description=Data e ora +d_dictionary.datatype.d_boolean.title=Booleano +d_dictionary.datatype.d_boolean.description=Booleano +d_dictionary.datatype.d_qname.title=Nome qualificato +d_dictionary.datatype.d_qname.description=Nome qualificato +d_dictionary.datatype.d_guid.title=Identificativo unico +d_dictionary.datatype.d_guid.description=Identificativo unico +d_dictionary.datatype.d_category.title=Categoria +d_dictionary.datatype.d_category.description=Categoria +d_dictionary.datatype.d_noderef.title=Riferimento +d_dictionary.datatype.d_noderef.description=Riferimento +d_dictionary.datatype.d_path.title=Percorso +d_dictionary.datatype.d_path.description=Percorso diff --git a/data-model/src/main/resources/alfresco/messages/dictionary-model_ja.properties b/data-model/src/main/resources/alfresco/messages/dictionary-model_ja.properties new file mode 100755 index 0000000000..f8322fa94b --- /dev/null +++ b/data-model/src/main/resources/alfresco/messages/dictionary-model_ja.properties @@ -0,0 +1,34 @@ +# Display labels for Dictionary Model + +d_dictionary.description=Alfresco\u30c7\u30a3\u30af\u30b7\u30e7\u30ca\u30ea\u30e2\u30c7\u30eb + +d_dictionary.datatype.d_any.title=\u4efb\u610f +d_dictionary.datatype.d_any.description=\u4efb\u610f +d_dictionary.datatype.d_text.title=\u30c6\u30ad\u30b9\u30c8 +d_dictionary.datatype.d_text.description=\u30c6\u30ad\u30b9\u30c8 +d_dictionary.datatype.d_content.title=\u30b3\u30f3\u30c6\u30f3\u30c4 +d_dictionary.datatype.d_content.description=\u30b3\u30f3\u30c6\u30f3\u30c4 +d_dictionary.datatype.d_int.title=\u6574\u6570 +d_dictionary.datatype.d_int.description=\u6574\u6570 +d_dictionary.datatype.d_long.title=\u9577\u6574\u6570 +d_dictionary.datatype.d_long.description=\u9577\u6574\u6570 +d_dictionary.datatype.d_float.title=\u6d6e\u52d5\u5c0f\u6570 +d_dictionary.datatype.d_float.description=\u6d6e\u52d5\u5c0f\u6570 +d_dictionary.datatype.d_double.title=\u500d\u7cbe\u5ea6\u6d6e\u52d5\u5c0f\u6570 +d_dictionary.datatype.d_double.description=\u500d\u7cbe\u5ea6\u6d6e\u52d5\u5c0f\u6570 +d_dictionary.datatype.d_date.title=\u65e5\u4ed8 +d_dictionary.datatype.d_date.description=\u65e5\u4ed8 +d_dictionary.datatype.d_datetime.title=\u65e5\u6642 +d_dictionary.datatype.d_datetime.description=\u65e5\u6642 +d_dictionary.datatype.d_boolean.title=\u8ad6\u7406\u578b +d_dictionary.datatype.d_boolean.description=\u8ad6\u7406\u578b +d_dictionary.datatype.d_qname.title=\u4fee\u98fe\u540d +d_dictionary.datatype.d_qname.description=\u4fee\u98fe\u540d +d_dictionary.datatype.d_guid.title=\u4e00\u610f\u8b58\u5225\u5b50 +d_dictionary.datatype.d_guid.description=\u4e00\u610f\u8b58\u5225\u5b50 +d_dictionary.datatype.d_category.title=\u30ab\u30c6\u30b4\u30ea +d_dictionary.datatype.d_category.description=\u30ab\u30c6\u30b4\u30ea +d_dictionary.datatype.d_noderef.title=\u53c2\u7167 +d_dictionary.datatype.d_noderef.description=\u53c2\u7167 +d_dictionary.datatype.d_path.title=\u30d1\u30b9 +d_dictionary.datatype.d_path.description=\u30d1\u30b9 diff --git a/data-model/src/main/resources/alfresco/messages/dictionary-model_nb.properties b/data-model/src/main/resources/alfresco/messages/dictionary-model_nb.properties new file mode 100755 index 0000000000..7139a64ae5 --- /dev/null +++ b/data-model/src/main/resources/alfresco/messages/dictionary-model_nb.properties @@ -0,0 +1,34 @@ +# Display labels for Dictionary Model + +d_dictionary.description=Alfresco-ordlistemodell + +d_dictionary.datatype.d_any.title=Enhver +d_dictionary.datatype.d_any.description=Enhver +d_dictionary.datatype.d_text.title=Tekst +d_dictionary.datatype.d_text.description=Tekst +d_dictionary.datatype.d_content.title=Innhold +d_dictionary.datatype.d_content.description=Innhold +d_dictionary.datatype.d_int.title=Heltall +d_dictionary.datatype.d_int.description=Heltall +d_dictionary.datatype.d_long.title=Lang +d_dictionary.datatype.d_long.description=Lang +d_dictionary.datatype.d_float.title=Flyt +d_dictionary.datatype.d_float.description=Flyt +d_dictionary.datatype.d_double.title=Dobbel +d_dictionary.datatype.d_double.description=Dobbel +d_dictionary.datatype.d_date.title=Dato +d_dictionary.datatype.d_date.description=Dato +d_dictionary.datatype.d_datetime.title=Dato og klokkeslett +d_dictionary.datatype.d_datetime.description=Dato og klokkeslett +d_dictionary.datatype.d_boolean.title=Boolsk +d_dictionary.datatype.d_boolean.description=Boolsk +d_dictionary.datatype.d_qname.title=Kvalifisert navn +d_dictionary.datatype.d_qname.description=Kvalifisert navn +d_dictionary.datatype.d_guid.title=Unik identifikator +d_dictionary.datatype.d_guid.description=Unik identifikator +d_dictionary.datatype.d_category.title=Kategori +d_dictionary.datatype.d_category.description=Kategori +d_dictionary.datatype.d_noderef.title=Referanse +d_dictionary.datatype.d_noderef.description=Referanse +d_dictionary.datatype.d_path.title=Bane +d_dictionary.datatype.d_path.description=Bane diff --git a/data-model/src/main/resources/alfresco/messages/dictionary-model_nl.properties b/data-model/src/main/resources/alfresco/messages/dictionary-model_nl.properties new file mode 100755 index 0000000000..08e61a6f44 --- /dev/null +++ b/data-model/src/main/resources/alfresco/messages/dictionary-model_nl.properties @@ -0,0 +1,34 @@ +# Display labels for Dictionary Model + +d_dictionary.description=Alfresco-woordenboekmodel + +d_dictionary.datatype.d_any.title=Willekeurig +d_dictionary.datatype.d_any.description=Willekeurig +d_dictionary.datatype.d_text.title=Tekst +d_dictionary.datatype.d_text.description=Tekst +d_dictionary.datatype.d_content.title=Content +d_dictionary.datatype.d_content.description=Content +d_dictionary.datatype.d_int.title=Integer +d_dictionary.datatype.d_int.description=Integer +d_dictionary.datatype.d_long.title=Long +d_dictionary.datatype.d_long.description=Long +d_dictionary.datatype.d_float.title=Float +d_dictionary.datatype.d_float.description=Float +d_dictionary.datatype.d_double.title=Double +d_dictionary.datatype.d_double.description=Double +d_dictionary.datatype.d_date.title=Datum +d_dictionary.datatype.d_date.description=Datum +d_dictionary.datatype.d_datetime.title=Datum en tijd +d_dictionary.datatype.d_datetime.description=Datum en tijd +d_dictionary.datatype.d_boolean.title=Boolean +d_dictionary.datatype.d_boolean.description=Boolean +d_dictionary.datatype.d_qname.title=Gekwalificeerde naam +d_dictionary.datatype.d_qname.description=Gekwalificeerde naam +d_dictionary.datatype.d_guid.title=Unieke id +d_dictionary.datatype.d_guid.description=Unieke id +d_dictionary.datatype.d_category.title=Categorie +d_dictionary.datatype.d_category.description=Categorie +d_dictionary.datatype.d_noderef.title=Verwijzing +d_dictionary.datatype.d_noderef.description=Verwijzing +d_dictionary.datatype.d_path.title=Pad +d_dictionary.datatype.d_path.description=Pad diff --git a/data-model/src/main/resources/alfresco/messages/dictionary-model_pt_BR.properties b/data-model/src/main/resources/alfresco/messages/dictionary-model_pt_BR.properties new file mode 100644 index 0000000000..90111a6018 --- /dev/null +++ b/data-model/src/main/resources/alfresco/messages/dictionary-model_pt_BR.properties @@ -0,0 +1,34 @@ +# Display labels for Dictionary Model + +d_dictionary.description=Modelo de dicion\u00e1rio do Alfresco + +d_dictionary.datatype.d_any.title=Qualquer +d_dictionary.datatype.d_any.description=Qualquer +d_dictionary.datatype.d_text.title=Texto +d_dictionary.datatype.d_text.description=Texto +d_dictionary.datatype.d_content.title=Conte\u00fado +d_dictionary.datatype.d_content.description=Conte\u00fado +d_dictionary.datatype.d_int.title=Inteiro +d_dictionary.datatype.d_int.description=Inteiro +d_dictionary.datatype.d_long.title=Longo +d_dictionary.datatype.d_long.description=Longo +d_dictionary.datatype.d_float.title=Flutuante +d_dictionary.datatype.d_float.description=Flutuante +d_dictionary.datatype.d_double.title=Duplo +d_dictionary.datatype.d_double.description=Duplo +d_dictionary.datatype.d_date.title=Data +d_dictionary.datatype.d_date.description=Data +d_dictionary.datatype.d_datetime.title=Data e hora +d_dictionary.datatype.d_datetime.description=Data e hora +d_dictionary.datatype.d_boolean.title=Booleano +d_dictionary.datatype.d_boolean.description=Booleano +d_dictionary.datatype.d_qname.title=Nome qualificado +d_dictionary.datatype.d_qname.description=Nome qualificado +d_dictionary.datatype.d_guid.title=Identificador exclusivo +d_dictionary.datatype.d_guid.description=Identificador exclusivo +d_dictionary.datatype.d_category.title=Categoria +d_dictionary.datatype.d_category.description=Categoria +d_dictionary.datatype.d_noderef.title=Refer\u00eancia +d_dictionary.datatype.d_noderef.description=Refer\u00eancia +d_dictionary.datatype.d_path.title=Caminho +d_dictionary.datatype.d_path.description=Caminho diff --git a/data-model/src/main/resources/alfresco/messages/dictionary-model_ru.properties b/data-model/src/main/resources/alfresco/messages/dictionary-model_ru.properties new file mode 100755 index 0000000000..c89d6280d0 --- /dev/null +++ b/data-model/src/main/resources/alfresco/messages/dictionary-model_ru.properties @@ -0,0 +1,34 @@ +# Display labels for Dictionary Model + +d_dictionary.description=\u041c\u043e\u0434\u0435\u043b\u044c \u0441\u043b\u043e\u0432\u0430\u0440\u044f Alfresco + +d_dictionary.datatype.d_any.title=\u041b\u044e\u0431\u043e\u0439 +d_dictionary.datatype.d_any.description=\u041b\u044e\u0431\u043e\u0439 +d_dictionary.datatype.d_text.title=\u0422\u0435\u043a\u0441\u0442 +d_dictionary.datatype.d_text.description=\u0422\u0435\u043a\u0441\u0442 +d_dictionary.datatype.d_content.title=\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 +d_dictionary.datatype.d_content.description=\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 +d_dictionary.datatype.d_int.title=Integer +d_dictionary.datatype.d_int.description=Integer +d_dictionary.datatype.d_long.title=Long +d_dictionary.datatype.d_long.description=Long +d_dictionary.datatype.d_float.title=Float +d_dictionary.datatype.d_float.description=Float +d_dictionary.datatype.d_double.title=Double +d_dictionary.datatype.d_double.description=Double +d_dictionary.datatype.d_date.title=\u0414\u0430\u0442\u0430 +d_dictionary.datatype.d_date.description=\u0414\u0430\u0442\u0430 +d_dictionary.datatype.d_datetime.title=\u0414\u0430\u0442\u0430 \u0438 \u0432\u0440\u0435\u043c\u044f +d_dictionary.datatype.d_datetime.description=\u0414\u0430\u0442\u0430 \u0438 \u0432\u0440\u0435\u043c\u044f +d_dictionary.datatype.d_boolean.title=Boolean +d_dictionary.datatype.d_boolean.description=Boolean +d_dictionary.datatype.d_qname.title=\u041f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f +d_dictionary.datatype.d_qname.description=\u041f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f +d_dictionary.datatype.d_guid.title=\u0423\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 +d_dictionary.datatype.d_guid.description=\u0423\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 +d_dictionary.datatype.d_category.title=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f +d_dictionary.datatype.d_category.description=\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f +d_dictionary.datatype.d_noderef.title=\u0421\u0441\u044b\u043b\u043a\u0430 +d_dictionary.datatype.d_noderef.description=\u0421\u0441\u044b\u043b\u043a\u0430 +d_dictionary.datatype.d_path.title=\u041f\u0443\u0442\u044c +d_dictionary.datatype.d_path.description=\u041f\u0443\u0442\u044c diff --git a/data-model/src/main/resources/alfresco/messages/dictionary-model_zh_CN.properties b/data-model/src/main/resources/alfresco/messages/dictionary-model_zh_CN.properties new file mode 100755 index 0000000000..34ab9b1f0a --- /dev/null +++ b/data-model/src/main/resources/alfresco/messages/dictionary-model_zh_CN.properties @@ -0,0 +1,34 @@ +# Display labels for Dictionary Model + +d_dictionary.description=Alfresco \u5b57\u5178\u6a21\u578b + +d_dictionary.datatype.d_any.title=\u4efb\u4f55 +d_dictionary.datatype.d_any.description=\u4efb\u4f55 +d_dictionary.datatype.d_text.title=\u6587\u672c +d_dictionary.datatype.d_text.description=\u6587\u672c +d_dictionary.datatype.d_content.title=\u5185\u5bb9 +d_dictionary.datatype.d_content.description=\u5185\u5bb9 +d_dictionary.datatype.d_int.title=\u6574\u6570 +d_dictionary.datatype.d_int.description=\u6574\u6570 +d_dictionary.datatype.d_long.title=\u957f\u6574\u578b +d_dictionary.datatype.d_long.description=\u957f\u6574\u578b +d_dictionary.datatype.d_float.title=\u6d6e\u70b9\u578b +d_dictionary.datatype.d_float.description=\u6d6e\u70b9\u578b +d_dictionary.datatype.d_double.title=\u53cc\u7cbe\u5ea6 +d_dictionary.datatype.d_double.description=\u53cc\u7cbe\u5ea6 +d_dictionary.datatype.d_date.title=\u65e5\u671f +d_dictionary.datatype.d_date.description=\u65e5\u671f +d_dictionary.datatype.d_datetime.title=\u65e5\u671f\u548c\u65f6\u95f4 +d_dictionary.datatype.d_datetime.description=\u65e5\u671f\u548c\u65f6\u95f4 +d_dictionary.datatype.d_boolean.title=\u5e03\u5c14\u503c +d_dictionary.datatype.d_boolean.description=\u5e03\u5c14\u503c +d_dictionary.datatype.d_qname.title=\u9650\u5b9a\u540d\u79f0 +d_dictionary.datatype.d_qname.description=\u9650\u5b9a\u540d\u79f0 +d_dictionary.datatype.d_guid.title=\u552f\u4e00\u6807\u8bc6\u7b26 +d_dictionary.datatype.d_guid.description=\u552f\u4e00\u6807\u8bc6\u7b26 +d_dictionary.datatype.d_category.title=\u7c7b\u522b +d_dictionary.datatype.d_category.description=\u7c7b\u522b +d_dictionary.datatype.d_noderef.title=\u5f15\u7528 +d_dictionary.datatype.d_noderef.description=\u5f15\u7528 +d_dictionary.datatype.d_path.title=\u8def\u5f84 +d_dictionary.datatype.d_path.description=\u8def\u5f84 diff --git a/data-model/src/main/resources/alfresco/mimetype/mimetype-map-openoffice.xml b/data-model/src/main/resources/alfresco/mimetype/mimetype-map-openoffice.xml new file mode 100644 index 0000000000..f610eec30d --- /dev/null +++ b/data-model/src/main/resources/alfresco/mimetype/mimetype-map-openoffice.xml @@ -0,0 +1,101 @@ + + + + + + + + odt + + + ott + + + oth + + + odm + + + odg + + + otg + + + odp + + + otp + + + ods + + + ots + + + odc + + + odf + + + odb + + + odi + + + + + sxc + + + stc + + + sxd + + + sxi + + + sti + + + sxw + + + stw + + + + + sda + + + sdc + + + sdd + + + sdp + + + sds + + + sdw + + + sgl + + + smf + + + + + diff --git a/data-model/src/main/resources/alfresco/mimetype/mimetype-map.xml b/data-model/src/main/resources/alfresco/mimetype/mimetype-map.xml new file mode 100644 index 0000000000..b2a7a663f5 --- /dev/null +++ b/data-model/src/main/resources/alfresco/mimetype/mimetype-map.xml @@ -0,0 +1,623 @@ + + + + + + + json + + + + eps + + + + jp2 + jpx + jpm + jpc + j2k + jpf + + + + mpp + + + + psd + + + + + + ppj + prproj + + + + asnd + + + + aep + + + aet + + + + fm + + + + pmd + pm6 + p65 + pm + + + + prn + + + + txt + sql + properties + ftl + ini + bat + sh + log + rte + + + csv + + + + html + htm + shtml + body + xsd + + + mw + + + xhtml + + + + ps + + + ai + + + aiff + aif + aifc + + + acp + + + vsd + + + vsdx + + + xdp + + + au + snd + + + + ogv + + + oga + spx + + + ogg + + + ogx + + + flac + + + + webm + + + + avi + qvi + + + asf + asx + + + wmv + + + wma + + + avx + + + bcpio + + + bin + exe + + + exe + + + cdf + nc + + + cer + + + cgm + + + class + + + cpio + + + csh + + + css + + + wpd + + + xml + dtd + xslt + xsl + xsd + + + dvi + + + etx + + + gif + + + gtar + + + gzip + + + hdf + + + hqx + + + ics + + + ief + + + bmp + + + jpg + jpeg + jpe + + + svg + + + dng + + + 3fr + + + raf + + + cr2 + crw + + + k25 + kdc + dcs + drf + + + mrw + + + nef + nrw + + + orf + + + pef + ptx + + + arw + srf + sr2 + + + x3f + + + rw2 + + + rwl + + + r3d + + + js + + + latex + + + man + + + me + + + ms + + + mif + + + mpg + mpeg + mpe + m1v + m2v + + + mp3 + mp2 + + + m4a + m4b + mp4a + + + mp4 + mp4v + mpg4 + + + m4v + + + mpeg2 + + + ts + m2ts + + + mov + qt + + + 3gp + + + 3g2 + 3gp2 + + + movie + mpv2 + mv + + + oda + + + pbm + + + pdf + + + pgm + + + png + + + pnm + rpnm + + + ppm + + + ras + + + rgb + + + tr + t + roff + + + rtf + + + rtx + + + sgml + sgm + + + gml + + + sh + + + shar + + + src + + + sv4cpio + + + sv4crc + + + air + + + swf + + + flv + + + fla + + + dita + ditaval + ditamap + + + tar + + + tcl + + + tex + + + texinfo + texi + + + tiff + tif + + + tsv + + + ustar + + + wav + + + wrl + + + xbm + + + xpm + + + xwd + + + z + + + zip + war + jar + ear + + + apk + + + + dwg + + + dwt + + + + eml + + + msg + + + doc + dot + + + + ppt + pps + pot + ppa + + + + xls + xlt + xlm + + + + + + docx + + + docm + + + dotx + + + dotm + + + + pptx + + + pptm + + + ppsx + + + ppsm + + + potx + + + potm + + + ppam + + + sldx + + + sldm + + + + xlsx + + + xltx + + + xlsm + + + xltm + + + xlam + + + xlsb + + + + fxp + + + indd + ind + + + + key + + + pages + + + numbers + + + + + md + + + + + rss + + + + java + + + jsp + + + jar + + + rar + + + + + + diff --git a/data-model/src/main/resources/alfresco/model/cmisModel.xml b/data-model/src/main/resources/alfresco/model/cmisModel.xml new file mode 100644 index 0000000000..20d02b74f6 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/cmisModel.xml @@ -0,0 +1,439 @@ + + + CMIS Model Definitions + 1.0 + + + + + + + + + + + + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + java.lang.String + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + java.lang.String + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + java.lang.String + + + + + + + + + + notallowed + allowed + required + + + + + + + + + + + + Object Id + The unique object id (a node ref) + cmis:id + true + false + false + + false + + + + Object Type Id + Id of the object’s type + cmis:id + true + true + false + + false + + + + Base Type Id + Id of the base object type for the object + cmis:id + true + false + false + + true + + + + Name + Name + d:text + false + true + false + + both + + + + Created by + The authority who created this object + d:text + true + false + false + + false + + + + Creation Date + The object creation date + d:datetime + true + false + false + + false + + + + Last Modified By + The authority who last modified this object + d:text + true + false + false + + false + + + + Last Modified Date + The date this object was last modified + d:datetime + true + false + false + + false + + + + Change token + Change Token + d:text + true + false + false + + + + Alfresco Node Ref + Alfresco Node Ref + cmis:id + true + false + false + + + + + Description + Description + d:text + false + false + false + + true + + + + Secondary Object Type Ids + Ids of the secondary object types for the object + cmis:id + false + false + true + + true + + + + + + + Document + Document Type + cmisext:object + + + Is Immutable + Is the document immutable? + d:boolean + true + false + false + + + + Is Latest Version + Is this the latest version of the document? + d:boolean + true + false + false + + + + Is Major Version + Is this a major version of the document? + d:boolean + true + false + false + + + + Is Latest Major Version + Is this the latest major version of the document? + d:boolean + true + false + false + + + + Version Label + The version label + d:text + true + false + false + + + + Version series id + The version series id + cmis:id + true + false + false + + + + Is Version Series Checked Out + Is the version series checked out? + d:boolean + true + false + false + + + + Version Series Checked Out By + The authority who checked out this document version series + d:text + true + false + false + + + + Version Series Checked Out Id + The checked out version series id + cmis:id + true + false + false + + + + Checkin Comment + The checkin comment + d:text + true + false + false + + + + Content Stream Length + The length of the content stream + d:long + true + false + false + + false + + + + Content Stream MIME Type + The content stream MIME type + d:text + true + false + false + + false + + + + Content Stream Filename + The content stream filename + d:text + true + false + false + + true + + + + Content Stream Id + Id of the stream + cmis:id + true + false + false + + + + + Is private working copy + Indicates if this instance is a private working copy + d:boolean + true + false + false + + + + + + + Folder + Folder Type + cmisext:object + + + Parent Id + The parent id of the folder + cmis:id + true + false + false + + false + + + + Path + The fully qualified path to this folder/description + d:text + true + false + false + + + + Allowed Child Object Types Ids + The allowed child object type ids + cmis:id + true + false + true + + + + + + + Relationship + Relationship Type + cmisext:object + + + Source Id + The source id for the relationship + cmis:id + true + true + false + + + + Target Id + The target id for the relationship + cmis:id + true + true + false + + + + + + + Policy + Policy Type + cmisext:object + + + Policy Text + The policy text + d:text + true + true + false + + + + + + + Secondary Type + Secondary Type + cmisext:object + + + + + + Item Type + CMIS Item + cmisext:object + + + + + + Aspects + Aspects Type + cmis:policy + + + + + \ No newline at end of file diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers.properties new file mode 100644 index 0000000000..94a1f655c2 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers.properties @@ -0,0 +1,18 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_any.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser +d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser +d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser +d_dictionary.datatype.d_int.analyzer=org.alfresco.repo.search.impl.lucene.analysis.IntegerAnalyser +d_dictionary.datatype.d_long.analyzer=org.alfresco.repo.search.impl.lucene.analysis.LongAnalyser +d_dictionary.datatype.d_float.analyzer=org.alfresco.repo.search.impl.lucene.analysis.FloatAnalyser +d_dictionary.datatype.d_double.analyzer=org.alfresco.repo.search.impl.lucene.analysis.DoubleAnalyser +d_dictionary.datatype.d_date.analyzer=org.alfresco.repo.search.impl.lucene.analysis.DateAnalyser +d_dictionary.datatype.d_datetime.analyzer=org.alfresco.repo.search.impl.lucene.analysis.DateAnalyser +d_dictionary.datatype.d_boolean.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser +d_dictionary.datatype.d_qname.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser +d_dictionary.datatype.d_guid.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser +d_dictionary.datatype.d_category.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser +d_dictionary.datatype.d_noderef.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser +d_dictionary.datatype.d_path.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser +d_dictionary.datatype.d_locale.analyzer=org.alfresco.repo.search.impl.lucene.analysis.LowerCaseVerbatimAnalyser diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_cs.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_cs.properties new file mode 100644 index 0000000000..a808ef4aba --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_cs.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.cz.CzechAnalyzer +d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.cz.CzechAnalyzer diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_da.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_da.properties new file mode 100644 index 0000000000..f24e343726 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_da.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.DanishSnowballAnalyser +d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.DanishSnowballAnalyser diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_de.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_de.properties new file mode 100644 index 0000000000..01b1086291 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_de.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.de.GermanAnalyzer +d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.de.GermanAnalyzer diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_el.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_el.properties new file mode 100644 index 0000000000..3be1f75e67 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_el.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.el.GreekAnalyzer +d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.el.GreekAnalyzer diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_en.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_en.properties new file mode 100644 index 0000000000..9b92c0b6d0 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_en.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser +d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_es.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_es.properties new file mode 100644 index 0000000000..43da2753ec --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_es.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.SpanishSnowballAnalyser +d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.SpanishSnowballAnalyser diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_fi.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_fi.properties new file mode 100644 index 0000000000..eb48e159d9 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_fi.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.FinnishSnowballAnalyser +d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.FinnishSnowballAnalyser diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_fr.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_fr.properties new file mode 100644 index 0000000000..0532029d20 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_fr.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.fr.FrenchAnalyzer +d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.fr.FrenchAnalyzer diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_it.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_it.properties new file mode 100644 index 0000000000..341d8716fd --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_it.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.ItalianSnowballAnalyser +d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.ItalianSnowballAnalyser diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_ja.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_ja.properties new file mode 100644 index 0000000000..e3adf49bba --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_ja.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.cjk.CJKAnalyzer +d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.cjk.CJKAnalyzer diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_ko.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_ko.properties new file mode 100644 index 0000000000..e3adf49bba --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_ko.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.cjk.CJKAnalyzer +d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.cjk.CJKAnalyzer diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_nl.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_nl.properties new file mode 100644 index 0000000000..d630049498 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_nl.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.nl.DutchAnalyzer +d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.nl.DutchAnalyzer diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_no.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_no.properties new file mode 100644 index 0000000000..32f779db95 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_no.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.NorwegianSnowballAnalyser +d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.NorwegianSnowballAnalyser diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_pt.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_pt.properties new file mode 100644 index 0000000000..941719040c --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_pt.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.PortugueseSnowballAnalyser +d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.PortugueseSnowballAnalyser diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_pt_BR.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_pt_BR.properties new file mode 100644 index 0000000000..d9fcc7a929 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_pt_BR.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.br.BrazilianAnalyzer +d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.br.BrazilianAnalyzer diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_ru.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_ru.properties new file mode 100644 index 0000000000..2db4278326 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_ru.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.ru.RussianAnalyzer +d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.ru.RussianAnalyzer diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_sv.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_sv.properties new file mode 100644 index 0000000000..81e2cb4c22 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_sv.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.alfresco.repo.search.impl.lucene.analysis.SwedishSnowballAnalyser +d_dictionary.datatype.d_content.analyzer=org.alfresco.repo.search.impl.lucene.analysis.SwedishSnowballAnalyser diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_th.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_th.properties new file mode 100644 index 0000000000..aa0400a3d8 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_th.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.th.ThaiAnalyzer +d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.th.ThaiAnalyzer diff --git a/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_zh.properties b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_zh.properties new file mode 100644 index 0000000000..55cf861ae5 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dataTypeAnalyzers_zh.properties @@ -0,0 +1,4 @@ +# Data Type Index Analyzers + +d_dictionary.datatype.d_text.analyzer=org.apache.lucene.analysis.cn.ChineseAnalyzer +d_dictionary.datatype.d_content.analyzer=org.apache.lucene.analysis.cn.ChineseAnalyzer diff --git a/data-model/src/main/resources/alfresco/model/dictionaryModel.xml b/data-model/src/main/resources/alfresco/model/dictionaryModel.xml new file mode 100644 index 0000000000..fe31d97726 --- /dev/null +++ b/data-model/src/main/resources/alfresco/model/dictionaryModel.xml @@ -0,0 +1,132 @@ + + + Alfresco Dictionary Model + Alfresco + 2005-09-29 + 1.0 + alfresco/model/dataTypeAnalyzers + + + + + + + + + + + + + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + java.lang.Object + + + + org.alfresco.repo.search.impl.lucene.analysis.EmptyAnalyser + javax.crypto.SealedObject + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + java.lang.String + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + org.alfresco.service.cmr.repository.MLText + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + org.alfresco.service.cmr.repository.ContentData + + + + org.alfresco.repo.search.impl.lucene.analysis.IntegerAnalyser + java.lang.Integer + + + + org.alfresco.repo.search.impl.lucene.analysis.LongAnalyser + java.lang.Long + + + + org.alfresco.repo.search.impl.lucene.analysis.FloatAnalyser + java.lang.Float + + + + org.alfresco.repo.search.impl.lucene.analysis.DoubleAnalyser + java.lang.Double + + + + org.alfresco.repo.search.impl.lucene.analysis.DateAnalyser + java.util.Date + + + + org.alfresco.repo.search.impl.lucene.analysis.DateTimeAnalyser + java.util.Date + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + java.lang.Boolean + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + org.alfresco.service.namespace.QName + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + org.alfresco.service.cmr.repository.NodeRef + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + org.alfresco.service.cmr.repository.ChildAssociationRef + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + org.alfresco.service.cmr.repository.AssociationRef + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + org.alfresco.service.cmr.repository.Path + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + org.alfresco.service.cmr.repository.NodeRef + + + + org.alfresco.repo.search.impl.lucene.analysis.VerbatimAnalyser + java.util.Locale + + + + org.alfresco.repo.search.impl.lucene.analysis.VerbatimAnalyser + org.alfresco.util.VersionNumber + + + + org.alfresco.repo.search.impl.lucene.analysis.VerbatimAnalyser + org.alfresco.service.cmr.repository.Period + + + + + + + + diff --git a/data-model/src/test/java/org/alfresco/opencmis/dictionary/CMISAbstractDictionaryServiceTest.java b/data-model/src/test/java/org/alfresco/opencmis/dictionary/CMISAbstractDictionaryServiceTest.java new file mode 100644 index 0000000000..04ea570136 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/opencmis/dictionary/CMISAbstractDictionaryServiceTest.java @@ -0,0 +1,110 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.opencmis.dictionary; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import org.alfresco.repo.cache.MemoryCache; +import org.alfresco.repo.cache.SimpleCache; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests for the {@link CMISAbstractDictionaryServiceTest} class. + * + * @author Matt Ward + */ +public class CMISAbstractDictionaryServiceTest +{ + // Class under test + private CMISAbstractDictionaryService dictService; + private SimpleCache cache; + private boolean initCalled; + private CMISDictionaryRegistry dictRegistry; + + @Before + public void setUp() throws Exception + { + dictService = new CMISAbstractDictionaryService() + { + @Override + protected CMISDictionaryRegistry getRegistry() + { + initCalled = true; + cache.put("cache_key", dictRegistry); + return dictRegistry; + } + + @Override + protected DictionaryInitializer getCoreDictionaryInitializer() + { + return null; + } + + @Override + protected DictionaryInitializer getTenantDictionaryInitializer() + { + return null; + } + }; + + dictRegistry = new CMISDictionaryRegistryImpl(); + cache = new MemoryCache(); + dictService.setSingletonCache(cache); + initCalled = false; + } + + @Test + public void canGetRegistryWhenInitNotYetCalled() + { + // Pre-conditions of test +// dictService.key_opencmis_dictionary_registry = null; +// assertNull(dictService.key_opencmis_dictionary_registry); + assertFalse(initCalled); + + CMISDictionaryRegistry registry = dictService.getRegistry(); + + assertTrue("init() should have been called.", initCalled); + assertSame(dictRegistry, registry); + } + + @Test + public void canGetRegistryWhenInitAlreadyCalled() + { + // Pre-conditions of test + dictService.getRegistry(); +// assertNotNull(dictService.key_opencmis_dictionary_registry); + assertTrue(initCalled); + + // Perform test + CMISDictionaryRegistry registry = dictService.getRegistry(); + + assertTrue("init() should have been called.", initCalled); + assertSame(dictRegistry, registry); + } +} diff --git a/data-model/src/test/java/org/alfresco/repo/cache/SimpleCacheTestBase.java b/data-model/src/test/java/org/alfresco/repo/cache/SimpleCacheTestBase.java new file mode 100644 index 0000000000..4988972443 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/cache/SimpleCacheTestBase.java @@ -0,0 +1,129 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.cache; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +public abstract class SimpleCacheTestBase> +{ + protected T cache; + + @Before + public void setUp() throws Exception + { + cache = createCache(); + } + + protected abstract T createCache(); + + @Test + public void canStoreNullValues() + { + cache.put(2, null); + assertEquals(null, cache.get(2)); + // Check that the key has an entry against it. + assertTrue(cache.contains(2)); + + // Ensure that a key that has not been assigned is discernable + // from a key that has been assigned a null value. + assertEquals(null, cache.get(4)); + assertFalse(cache.contains(4)); + } + + @Test + public void canRemoveItems() + { + cache.put(1, "hello"); + cache.put(2, "world"); + assertEquals("hello", cache.get(1)); + assertEquals("world", cache.get(2)); + + cache.remove(2); + assertEquals("hello", cache.get(1)); + assertEquals(null, cache.get(2)); + assertEquals(false, cache.contains(2)); + } + + @Test + public void canClearItems() + { + cache.put(1, "hello"); + cache.put(2, "world"); + assertEquals("hello", cache.get(1)); + assertEquals("world", cache.get(2)); + + cache.clear(); + + assertEquals(null, cache.get(1)); + assertEquals(false, cache.contains(1)); + assertEquals(null, cache.get(2)); + assertEquals(false, cache.contains(2)); + } + + @Test + public void canGetKeys() + { + cache.put(3, "blue"); + cache.put(12, "red"); + cache.put(43, "olive"); + + List keys = new ArrayList(cache.getKeys()); + Collections.sort(keys); + + Iterator it = keys.iterator(); + assertEquals(3, it.next().intValue()); + assertEquals(12, it.next().intValue()); + assertEquals(43, it.next().intValue()); + assertFalse("There should be no more keys.", it.hasNext()); + } + + @Test + public void noConcurrentModificationException() + { + cache.put(1, "1"); + cache.put(2, "2"); + cache.put(3, "3"); + cache.put(4, "4"); + + Iterator i = cache.getKeys().iterator(); + i.next(); + i.next(); + + cache.put(5, "5"); + + // Causes a ConcurrentModificationException with a java.util.LinkedHashMap + i.next(); + } + +} diff --git a/data-model/src/test/java/org/alfresco/repo/content/DataModelContentTestSuite.java b/data-model/src/test/java/org/alfresco/repo/content/DataModelContentTestSuite.java new file mode 100644 index 0000000000..da87933778 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/content/DataModelContentTestSuite.java @@ -0,0 +1,51 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.alfresco.repo.content.encoding.CharsetFinderTest; + +/** + * Suite for content-related tests. + * + * This includes all the tests that need a full context, the + * rest are in {@link ContentMinimalContextTestSuite} + * + * @author Derek Hulley + */ +public class DataModelContentTestSuite extends TestSuite +{ + public static Test suite() + { + TestSuite suite = new TestSuite(); + + suite.addTestSuite(CharsetFinderTest.class); + suite.addTestSuite(MimetypeMapTest.class); + return suite; + } +} diff --git a/data-model/src/test/java/org/alfresco/repo/content/MimetypeMapTest.java b/data-model/src/test/java/org/alfresco/repo/content/MimetypeMapTest.java new file mode 100644 index 0000000000..338f3e7dda --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/content/MimetypeMapTest.java @@ -0,0 +1,599 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content; + +import junit.framework.TestCase; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentIOException; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentStreamListener; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.util.DataModelTestApplicationContextHelper; +import org.springframework.context.ApplicationContext; +import org.springframework.extensions.config.ConfigDeployment; +import org.springframework.extensions.config.ConfigService; +import org.springframework.extensions.config.ConfigSource; +import org.springframework.extensions.config.xml.XMLConfigService; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** + * @see org.alfresco.repo.content.MimetypeMap + * @see org.alfresco.repo.content.MimetypeMapContentTest + * + * @author Derek Hulley + */ +public class MimetypeMapTest extends TestCase +{ + private static ApplicationContext ctx = DataModelTestApplicationContextHelper.getApplicationContext(); + + private MimetypeService mimetypeService; + private ConfigService configService; + + @Override + public void setUp() throws Exception + { + mimetypeService = (MimetypeService)ctx.getBean("mimetypeService"); + configService = ((MimetypeMap)mimetypeService).getConfigService(); + } + + @Override + protected void tearDown() throws Exception + { + ((MimetypeMap)mimetypeService).setConfigService(configService); + ((MimetypeMap)mimetypeService).init(); + } + + public void testExtensions() throws Exception + { + Map extensionsByMimetype = mimetypeService.getExtensionsByMimetype(); + Map mimetypesByExtension = mimetypeService.getMimetypesByExtension(); + + // plain text + assertEquals("txt", extensionsByMimetype.get("text/plain")); + assertEquals("text/plain", mimetypesByExtension.get("txt")); + assertEquals("text/plain", mimetypesByExtension.get("ftl")); + + // other text forms + assertEquals("text/csv", mimetypesByExtension.get("csv")); + assertEquals("text/html", mimetypesByExtension.get("html")); + + // JPEG + assertEquals("jpg", extensionsByMimetype.get("image/jpeg")); + assertEquals("image/jpeg", mimetypesByExtension.get("jpg")); + assertEquals("image/jpeg", mimetypesByExtension.get("jpeg")); + assertEquals("image/jpeg", mimetypesByExtension.get("jpe")); + + // MS Word + assertEquals("doc", extensionsByMimetype.get("application/msword")); + assertEquals("application/msword", mimetypesByExtension.get("doc")); + + // Star Office + assertEquals("sds", extensionsByMimetype.get("application/vnd.stardivision.chart")); + } + + public void testIsText() throws Exception + { + assertTrue(mimetypeService.isText(MimetypeMap.MIMETYPE_HTML)); + } + + public void testGetContentCharsetFinder() throws Exception + { + assertNotNull("No charset finder", mimetypeService.getContentCharsetFinder()); + } + + public void testMimetypeFromExtension() throws Exception + { + // test known mimetype + assertEquals("application/msword", mimetypeService.getMimetype("doc")); + // test case insensitivity + assertEquals("application/msword", mimetypeService.getMimetype("DOC")); + + // test fallback for unknown and missing + assertEquals(MimetypeMap.MIMETYPE_BINARY, mimetypeService.getMimetype(null)); + assertEquals(MimetypeMap.MIMETYPE_BINARY, mimetypeService.getMimetype("unknownext")); + } + + /** + * Tests guessing the mimetype from a filename. + * + * Note - The test for checking by filename + content are in the repo project + * @see org.alfresco.repo.content.MimetypeMapContentTest + */ + public void testGuessMimetypeForFilename() throws Exception + { + assertEquals("application/msword", mimetypeService.guessMimetype("something.doc")); + assertEquals("application/msword", mimetypeService.guessMimetype("SOMETHING.DOC")); + assertEquals(MimetypeMap.MIMETYPE_BINARY, mimetypeService.guessMimetype("noextension")); + assertEquals(MimetypeMap.MIMETYPE_BINARY, mimetypeService.guessMimetype("file.unknownext")); + + // Without a content reader, the behaviour is the same + assertEquals("application/msword", mimetypeService.guessMimetype("something.doc", (ContentReader)null)); + assertEquals("application/msword", mimetypeService.guessMimetype("SOMETHING.DOC", (ContentReader)null)); + assertEquals(MimetypeMap.MIMETYPE_BINARY, mimetypeService.guessMimetype("noextension", (ContentReader)null)); + assertEquals(MimetypeMap.MIMETYPE_BINARY, mimetypeService.guessMimetype("file.unknownext", (ContentReader)null)); + } + + private static final String MIMETYPE_1A = + " " + + " ext1a" + + " "; + private static final String MIMETYPE_1B = + " " + + " ext1a" + + " "; + private static final String MIMETYPE_1C = + " " + + " ext1a" + + " "; + private static final String MIMETYPE_1D = + " " + + " ext1a" + + " "; + private static final String MIMETYPE_1E = + " " + + " ext1a" + + " "; + private static final String MIMETYPE_1F = + " " + + " ext1a" + + " ext1b" + + " ext1c" + + " "; + private static final String MIMETYPE_1G = + " " + + " ext1c" + + " ext1b" + + " ext1a" + + " "; + + private static final String MIMETYPE_2A = + " " + + " ext2a" + + " "; + private static final String MIMETYPE_2B = + " " + + " ext2a" + + " "; + + private static final String MIMETYPE_3A = + " " + + " ext3a" + + " ext3b" + + " "; + + public void testNoDuplicates() throws Exception + { + setConfigService( + MIMETYPE_1A+ + MIMETYPE_2A+ + MIMETYPE_3A); + ((MimetypeMap)mimetypeService).init(); + + assertFalse("mimetype1 should not be text", mimetypeService.isText("mimetype1")); + assertEquals("ext1a", mimetypeService.getExtension("mimetype1")); + assertEquals("mimetype1", mimetypeService.getMimetype("ext1a")); + assertEquals("Mimetype ONE", mimetypeService.getDisplaysByMimetype().get("mimetype1")); + assertEquals("Extension ONE", mimetypeService.getDisplaysByExtension().get("ext1a")); + + assertTrue("mimetype2 should be text", mimetypeService.isText("mimetype2")); + assertEquals("mimetype2", mimetypeService.getMimetype("ext2a")); + + assertEquals("mimetype3", mimetypeService.getMimetype("ext3a")); + } + + public void testTypes() throws Exception + { + Collection types = mimetypeService.getMimetypes(null); + assertNotNull(types); + types = mimetypeService.getMimetypes("txt"); + assertNotNull(types); + + assertNull(mimetypeService.getMimetypeIfNotMatches(new DummyContentReader())); + } + + public void testMisc() throws Exception + { + MimetypeMap m = new MimetypeMap(null); + ContentReader reader = new DummyContentReader(MimetypeMap.MIMETYPE_VIDEO_QUICKTIME); + assertEquals(MimetypeMap.MIMETYPE_TEXT_PLAIN, mimetypeService.getMimetypeIfNotMatches(reader)); + assertEquals(MimetypeMap.MIMETYPE_TEXT_PLAIN, mimetypeService.guessMimetype("file.rm", reader.getContentInputStream())); + assertEquals(MimetypeMap.MIMETYPE_VIDEO_QUICKTIME, mimetypeService.guessMimetype("file.rm", reader)); + } + + public void testTypeBasedOnDetectedTypeAndExtension() throws Exception + { + ContentReader reader = new DummyContentReader(MimetypeMap.MIMETYPE_PDF, "%PDF\r"); + assertEquals(MimetypeMap.MIMETYPE_APPLICATION_ILLUSTRATOR, mimetypeService.guessMimetype("file.ai", reader.getContentInputStream())); + assertEquals(MimetypeMap.MIMETYPE_PDF, mimetypeService.guessMimetype("file.pdf", reader.getContentInputStream())); + + reader = new DummyContentReader(MimetypeMap.MIMETYPE_APPLICATION_PS, "%!PS"); + assertEquals(MimetypeMap.MIMETYPE_APPLICATION_EPS, mimetypeService.guessMimetype("file.eps", reader.getContentInputStream())); + assertEquals(MimetypeMap.MIMETYPE_APPLICATION_PS, mimetypeService.guessMimetype("file.ps", reader.getContentInputStream())); + } + + public void testDuplicates() throws Exception + { + setConfigService( + MIMETYPE_1A+MIMETYPE_1B+MIMETYPE_1C+MIMETYPE_1D+MIMETYPE_1E+MIMETYPE_1F+ // Change all values + MIMETYPE_2A+MIMETYPE_2B+ // duplicate removes isText + MIMETYPE_3A+MIMETYPE_3A); // identical + ((MimetypeMap)mimetypeService).init(); + + assertTrue("mimetype1 should have be reset to text", mimetypeService.isText("mimetype1")); + assertEquals("ext1b", mimetypeService.getExtension("mimetype1")); + assertEquals("mimetype1", mimetypeService.getMimetype("ext1a")); + assertEquals("mimetype1", mimetypeService.getMimetype("ext1b")); + assertEquals("mimetype1", mimetypeService.getMimetype("ext1c")); + assertEquals("Mimetype 1", mimetypeService.getDisplaysByMimetype().get("mimetype1")); + assertEquals("Extension 1", mimetypeService.getDisplaysByExtension().get("ext1a")); + + assertFalse("mimetype2 should have be reset to not text", mimetypeService.isText("mimetype2")); + assertEquals("mimetype2", mimetypeService.getMimetype("ext2a")); + + assertEquals("mimetype3", mimetypeService.getMimetype("ext3a")); + } + + private void setConfigService(final String mimetypes) + { + ConfigSource configSource = new ConfigSource() + { + @Override + public List getConfigDeployments() + { + String xml = + "" + + " " + + " " + + mimetypes + + " " + + " " + + ""; + List configs = new ArrayList(); + configs.add(new ConfigDeployment("name", new ByteArrayInputStream(xml.getBytes()))); + return configs; + } + }; + + ConfigService configService = new XMLConfigService(configSource); + ((XMLConfigService) configService).initConfig(); + ((MimetypeMap)mimetypeService).setConfigService(configService); + } + + public static class DummyContentReader implements ContentReader + { + private String mimetype; + private String content; + + public DummyContentReader() + { + this(MimetypeMap.MIMETYPE_HTML); + } + + public DummyContentReader(String mimetype) + { + this(mimetype, "@@/Y"); + } + + public DummyContentReader(String mimetype, String content) + { + this.mimetype = mimetype; + this.content = content; + } + + @Override + public ContentReader getReader() throws ContentIOException + { + return this; + } + + @Override + public boolean exists() + { + return false; + } + + @Override + public long getLastModified() + { + return 0; + } + + @Override + public boolean isClosed() + { + return false; + } + + @Override + public ReadableByteChannel getReadableChannel() throws ContentIOException + { + return null; + } + + @Override + public FileChannel getFileChannel() throws ContentIOException + { + return null; + } + + @Override + public InputStream getContentInputStream() throws ContentIOException + { + return new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)); + } + + @Override + public void getContent(OutputStream os) throws ContentIOException + { + + } + + @Override + public void getContent(File file) throws ContentIOException + { + + } + + @Override + public String getContentString() throws ContentIOException + { + return null; + } + + @Override + public String getContentString(int length) throws ContentIOException + { + return null; + } + + @Override + public boolean isChannelOpen() + { + return false; + } + + @Override + public void addListener(ContentStreamListener listener) + { + + } + + @Override + public long getSize() + { + return 5l; + } + + @Override + public ContentData getContentData() + { + return null; + } + + @Override + public String getContentUrl() + { + return null; + } + + @Override + public String getMimetype() + { + return mimetype; + } + + @Override + public void setMimetype(String mimetype) + { + + } + + @Override + public String getEncoding() + { + return StandardCharsets.UTF_8.toString(); + } + + @Override + public void setEncoding(String encoding) + { + + } + + @Override + public Locale getLocale() + { + return null; + } + + @Override + public void setLocale(Locale locale) + { + + } + } + + public static class DummyContentWriter implements ContentWriter + { + private String mimetype = MimetypeMap.MIMETYPE_AUDIO_MP4; + + public DummyContentWriter() + { + super(); + } + + public DummyContentWriter(String mimetype) + { + this.mimetype = mimetype; + } + + @Override + public ContentReader getReader() throws ContentIOException + { + return new DummyContentReader(); + } + + @Override + public boolean isClosed() + { + return false; + } + + @Override + public WritableByteChannel getWritableChannel() throws ContentIOException + { + return null; + } + + @Override + public FileChannel getFileChannel(boolean truncate) throws ContentIOException + { + return null; + } + + @Override + public OutputStream getContentOutputStream() throws ContentIOException + { + return null; + } + + @Override + public void putContent(ContentReader reader) throws ContentIOException + { + + } + + @Override + public void putContent(InputStream is) throws ContentIOException + { + + } + + @Override + public void putContent(File file) throws ContentIOException + { + + } + + @Override + public void putContent(String content) throws ContentIOException + { + + } + + @Override + public void guessMimetype(String filename) + { + + } + + @Override + public void guessEncoding() + { + + } + + @Override + public boolean isChannelOpen() + { + return false; + } + + @Override + public void addListener(ContentStreamListener listener) + { + + } + + @Override + public long getSize() + { + return 5l; + } + + @Override + public ContentData getContentData() + { + return null; + } + + @Override + public String getContentUrl() + { + return null; + } + + @Override + public String getMimetype() + { + return mimetype; + } + + @Override + public void setMimetype(String mimetype) + { + + } + + @Override + public String getEncoding() + { + return StandardCharsets.UTF_8.toString(); + } + + @Override + public void setEncoding(String encoding) + { + + } + + @Override + public Locale getLocale() + { + return new Locale("es"); + } + + @Override + public void setLocale(Locale locale) + { + + } + } +} diff --git a/data-model/src/test/java/org/alfresco/repo/content/encoding/CharsetFinderTest.java b/data-model/src/test/java/org/alfresco/repo/content/encoding/CharsetFinderTest.java new file mode 100644 index 0000000000..7dd7dc7dc8 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/content/encoding/CharsetFinderTest.java @@ -0,0 +1,136 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.content.encoding; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.Charset; + +import junit.framework.TestCase; + +import org.alfresco.encoding.CharactersetFinder; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.util.DataModelTestApplicationContextHelper; +import org.springframework.context.ApplicationContext; + +/** + * @see CharsetFinderTest + * @see CharactersetFinder + * + * @author Derek Hulley + */ +public class CharsetFinderTest extends TestCase +{ + private static ApplicationContext ctx = DataModelTestApplicationContextHelper.getApplicationContext(); + + private ContentCharsetFinder charsetFinder; + + @Override + public void setUp() throws Exception + { + charsetFinder = (ContentCharsetFinder) ctx.getBean("charset.finder"); + } + + public void testPlainText() throws Exception + { + String test = "The quick brown fox jumps over the lazy dog" + + "\n\nLe renard brun rapide saute par-dessus le chien paresseux" + + "\n\nDer schnelle braune Fuchs springt über den faulen Hund\n\n" + + "براون وكس السريع يقفز فوق الكلب كسالي"; + + // As UTF-8 + InputStream is = new BufferedInputStream(new ByteArrayInputStream(test.getBytes("UTF-8"))); + Charset charset = charsetFinder.getCharset(is, MimetypeMap.MIMETYPE_TEXT_PLAIN); + assertNotNull(charset); + assertEquals("UTF-8", charset.displayName()); + + // Now try with longer encodings + + // UTF-16 with byte order mark + is = new BufferedInputStream(new ByteArrayInputStream(test.getBytes("UTF-16"))); + charset = charsetFinder.getCharset(is, MimetypeMap.MIMETYPE_TEXT_PLAIN); + assertNotNull(charset); + assertEquals("UTF-16BE", charset.displayName()); + + is = new BufferedInputStream(new ByteArrayInputStream(test.getBytes("UnicodeBig"))); + charset = charsetFinder.getCharset(is, MimetypeMap.MIMETYPE_TEXT_PLAIN); + assertNotNull(charset); + assertEquals("UTF-16BE", charset.displayName()); + + is = new BufferedInputStream(new ByteArrayInputStream(test.getBytes("UnicodeLittle"))); + charset = charsetFinder.getCharset(is, MimetypeMap.MIMETYPE_TEXT_PLAIN); + assertNotNull(charset); + assertEquals("UTF-16LE", charset.displayName()); + + // UTF-32 with byte order mark + is = new BufferedInputStream(new ByteArrayInputStream(test.getBytes("UTF-32"))); + charset = charsetFinder.getCharset(is, MimetypeMap.MIMETYPE_TEXT_PLAIN); + assertNotNull(charset); + assertEquals("UTF-32BE", charset.displayName()); + } + + /** + * Tries with various 8 bit (non-unicode) encodings, such as + * ISO-8859-1 + */ + public void test8BitText() throws Exception + { + String for_iso_8859_1 = "En français où les choses sont accentués. En español, así"; + String for_iso_8859_7 = "Αυτό είναι στην ελληνική γλώσσα"; + String for_cp1251 = "Это в русском языке, который является кириллица"; + + InputStream is = new BufferedInputStream(new ByteArrayInputStream(for_iso_8859_1.getBytes("ISO-8859-1"))); + Charset charset = charsetFinder.getCharset(is, MimetypeMap.MIMETYPE_TEXT_PLAIN); + assertNotNull(charset); + assertEquals("ISO-8859-1", charset.displayName()); + + is = new BufferedInputStream(new ByteArrayInputStream(for_iso_8859_7.getBytes("ISO-8859-7"))); + charset = charsetFinder.getCharset(is, MimetypeMap.MIMETYPE_TEXT_PLAIN); + assertNotNull(charset); + assertEquals("ISO-8859-7", charset.displayName()); + + is = new BufferedInputStream(new ByteArrayInputStream(for_cp1251.getBytes("CP1251"))); + charset = charsetFinder.getCharset(is, MimetypeMap.MIMETYPE_TEXT_PLAIN); + assertNotNull(charset); + assertEquals("windows-1251", charset.displayName()); // AKA CP1251 + } + + /** + * Ensure that a Japanese HTML file encoded with Shift_JS is detected correctly + */ + public void testShiftJSHtml() throws Exception + { + String for_shift_js = "" + + "確認した結果を添付しますので、確認してください\r\n" + + "

    特許印紙の売りさばきに関する省令

    "; + InputStream is = new BufferedInputStream(new ByteArrayInputStream(for_shift_js.getBytes("Shift_JIS"))); + + Charset charset = charsetFinder.getCharset(is, MimetypeMap.MIMETYPE_TEXT_PLAIN); + assertNotNull(charset); + assertEquals("Shift_JIS", charset.displayName()); + } +} diff --git a/data-model/src/test/java/org/alfresco/repo/dictionary/AbstractModelTest.java b/data-model/src/test/java/org/alfresco/repo/dictionary/AbstractModelTest.java new file mode 100644 index 0000000000..3b81760c58 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/dictionary/AbstractModelTest.java @@ -0,0 +1,956 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import junit.framework.TestCase; +import org.alfresco.repo.tenant.SingleTServiceImpl; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.util.DynamicallySizedThreadPoolExecutor; +import org.alfresco.util.TraceableThreadFactory; +import org.alfresco.util.cache.DefaultAsynchronouslyRefreshedCacheRegistry; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class AbstractModelTest extends TestCase +{ + public static final String MODEL1_XML = + "" + + + " Another description" + + " Alfresco" + + " 2007-08-01" + + " 1.0" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " Base" + + " The Base Type 1" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + " Base" + + " The Base Type 2" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + " Base" + + " The Base Type 3" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + " " + + + " " + + " Base" + + " The Base Aspect 1" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + " Base" + + " The Base Aspect 2" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + " Base" + + " The Base Aspect 3" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + ""; + public static final String MODEL1_UPDATE1_XML = + "" + + + " Another description" + + " Alfresco" + + " 2007-08-01" + + " 1.0" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " Base" + + " The Base Type 1" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + " Base" + + " The Base Type 3" + + " " + + " " + + " d:text" + + " " + + " " + + " " + + + " " + + " Base" + + " The Base Type 4" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + " " + + + " " + + " Base" + + " The Base Aspect 1" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + " Base" + + " The Base Aspect 3" + + " " + + " " + + " d:int" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + " Base" + + " The Base Aspect 4" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + ""; + public static final String MODEL2_XML = + "" + + + " Another description" + + " Alfresco" + + " 2007-08-01" + + " 1.0" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " Base" + + " The Base Type 1" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + " " + + + " " + + " Base" + + " The Base Aspect 1" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + ""; + public static final String MODEL2_EXTRA_PROPERTIES_XML = + "" + + + " Another description" + + " Alfresco" + + " 2007-08-01" + + " 1.0" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " Base" + + " The Base Type 1" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " d:date" + + " " + + " " + + " " + + + " " + + + " " + + + " " + + " Base" + + " The Base Aspect 1" + + " " + + " " + + " d:boolean" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + ""; + public static final String MODEL3_XML = + "" + + + " Another description" + + " Alfresco" + + " 2007-08-01" + + " 1.0" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " Base" + + " The Base Type 1" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + " " + + + " " + + " Base" + + " The Base Aspect 1" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + ""; + public static final String MODEL3_EXTRA_TYPES_AND_ASPECTS_XML = + "" + + + " Another description" + + " Alfresco" + + " 2007-08-01" + + " 1.0" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " Base" + + " The Base Type 1" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + " Base" + + " The Base Type 2" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + " " + + + " " + + " Base" + + " The Base Aspect 1" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + " Base" + + " The Base Aspect 2" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + ""; + public static final String MODEL4_XML = + "" + + + " Another description" + + " Alfresco" + + " 2007-08-01" + + " 1.0" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " Base" + + " The Base Type 1" + + " " + + " " + + " d:text" + + " " + + " " + + " " + + + " " + + + " " + + + " " + + " Base" + + " The Base Aspect 1" + + " " + + " " + + " d:text" + + " " + + " " + + " " + + + " " + + + ""; + public static final String MODEL4_EXTRA_DEFAULT_ASPECT_XML = + "" + + + " Another description" + + " Alfresco" + + " 2007-08-01" + + " 1.0" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " Base" + + " The Base Type 1" + + " " + + " " + + " d:text" + + " " + + " " + + " " + + " test1:aspect1" + + " " + + " " + + + " " + + + " " + + + " " + + " Base" + + " The Base Aspect 1" + + " " + + " " + + " d:text" + + " " + + " " + + " " + + + " " + + + ""; + public static final String MODEL5_XML = + "" + + + " Another description" + + " Alfresco" + + " 2007-08-01" + + " 1.0" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " Base" + + " The Base Type 1" + + " " + + " " + + " d:text" + + " " + + " " + + " " + + + " " + + " Base" + + " The Base Type 2" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + " " + + + " " + + " Base" + + " The Base Aspect 1" + + " " + + " " + + " d:text" + + " " + + " " + + " " + + + " " + + " Base" + + " The Base Aspect 2" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + ""; + public static final String MODEL5_EXTRA_ASSOCIATIONS_XML = + "" + + + " Another description" + + " Alfresco" + + " 2007-08-01" + + " 1.0" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " Base" + + " The Base Type 1" + + " " + + " " + + " d:text" + + " " + + " " + + " " + + " " + + " " + + " false" + + " false" + + " " + + " " + + " test1:type2" + + " false" + + " false" + + " " + + " " + + " " + + " " + + + " " + + " Base" + + " The Base Type 2" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + " " + + + " " + + " Base" + + " The Base Aspect 1" + + " " + + " " + + " d:text" + + " " + + " " + + " " + + " " + + " " + + " test1:role1" + + " false" + + " true" + + " " + + " " + + " test1:aspect2" + + " test1:role2" + + " false" + + " true" + + " " + + " " + + " " + + " " + + + " " + + " Base" + + " The Base Aspect 2" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + ""; + public static final String MODEL6_XML = + "" + + + " Another description" + + " Alfresco" + + " 2007-08-01" + + " 1.0" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " Type1 Title" + + " Type1 Description" + + " " + + " " + + " Prop1 Title" + + " Prop1 Description" + + " d:text" + + " " + + " " + + " " + + + " " + + + " " + + + " " + + " Aspect1 Title" + + " Aspect1 Description" + + " " + + " " + + " Prop9 Title" + + " Prop9 Description" + + " d:text" + + " " + + " " + + " " + + + " " + + + ""; + public static final String MODEL6_UPDATE1_XML = + "" + + + " Another description - UPDATE1" + + " Alfresco - UPDATE1" + + " 2009-08-01" + + " 2.0" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " Type1 Title - UPDATE1" + + " Type1 Description - UPDATE1" + + " " + + " " + + " Prop1 Title - UPDATE1" + + " Prop1 Description - UPDATE1" + + " d:text" + + " " + + " " + + " " + + + " " + + + " " + + + " " + + " Aspect1 Title" + + " Aspect1 Description" + + " " + + " " + + " Prop9 Title - UPDATE1" + + " Prop9 Description - UPDATE1" + + " d:text" + + " " + + " " + + " " + + + " " + + + ""; + public static final String MODEL7_XML = + "" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " " + + + " " + + " " + + " test7:aspectA " + + " " + + " " + + + " " + + + ""; + public static final String MODEL7_EXTRA_PROPERTIES_MANDATORY_ASPECTS_XML = + "" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " " + + " " + + " Prop A1 " + + " d:text " + + " " + + " " + + " " + + + " " + + " " + + " test7:aspectA " + + " " + + " " + + + " " + + + ""; + + + public AbstractModelTest() + { + } + + DictionaryDAOImpl dictionaryDAO; + + /** + * Setup + */ + protected void setUp() throws Exception + { + // Initialise the Dictionary + TenantService tenantService = new SingleTServiceImpl(); + +// NamespaceDAOImpl namespaceDAO = new NamespaceDAOImpl(); +// namespaceDAO.setTenantService(tenantService); +// initNamespaceCaches(namespaceDAO); + + dictionaryDAO = new DictionaryDAOImpl(); + dictionaryDAO.setTenantService(tenantService); + + initDictionaryCaches(dictionaryDAO, tenantService); + + + // include Alfresco dictionary model + List bootstrapModels = new ArrayList(); + bootstrapModels.add("alfresco/model/dictionaryModel.xml"); + + DictionaryBootstrap bootstrap = new DictionaryBootstrap(); + bootstrap.setModels(bootstrapModels); + bootstrap.setDictionaryDAO(dictionaryDAO); + bootstrap.bootstrap(); + } + + void initDictionaryCaches(DictionaryDAOImpl dictionaryDAO, TenantService tenantService) + { + CompiledModelsCache compiledModelsCache = new CompiledModelsCache(); + compiledModelsCache.setDictionaryDAO(dictionaryDAO); + compiledModelsCache.setTenantService(tenantService); + compiledModelsCache.setRegistry(new DefaultAsynchronouslyRefreshedCacheRegistry()); + TraceableThreadFactory threadFactory = new TraceableThreadFactory(); + threadFactory.setThreadDaemon(true); + threadFactory.setThreadPriority(Thread.NORM_PRIORITY); + + ThreadPoolExecutor threadPoolExecutor = new DynamicallySizedThreadPoolExecutor(20, 20, 90, TimeUnit.SECONDS, new LinkedBlockingQueue(), threadFactory, + new ThreadPoolExecutor.CallerRunsPolicy()); + compiledModelsCache.setThreadPoolExecutor(threadPoolExecutor); + dictionaryDAO.setDictionaryRegistryCache(compiledModelsCache); + dictionaryDAO.init(); + } + + public void testIsSetup() + { + assertNotNull(dictionaryDAO); + } +} \ No newline at end of file diff --git a/data-model/src/test/java/org/alfresco/repo/dictionary/DictionaryComponentTest.java b/data-model/src/test/java/org/alfresco/repo/dictionary/DictionaryComponentTest.java new file mode 100644 index 0000000000..6e11619e79 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/dictionary/DictionaryComponentTest.java @@ -0,0 +1,162 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.i18n.StaticMessageLookup; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + +import java.io.ByteArrayInputStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.Locale; + +/** + * DictionaryNamespaceComponent and DictionaryComponent mostly delegate to other methods. This test is + * really about exercising all of the public endpoints. + * + * @author Gethin James + */ +public class DictionaryComponentTest extends AbstractModelTest +{ + DictionaryNamespaceComponent ndc; + + protected void setUp() throws Exception + { + super.setUp(); + NamespaceDAO nao = mock(NamespaceDAO.class); + when(nao.getPrefixes(anyString())).thenReturn(Arrays.asList("pref1")); + when(nao.getPrefixes()).thenReturn(Arrays.asList("pref1", "pref2")); + when(nao.getURIs()).thenReturn(Arrays.asList("uri1", "uri2")); + when(nao.getNamespaceURI(anyString())).thenReturn("uri1"); + ndc = new DictionaryNamespaceComponent(); + ndc.setNamespaceDAO(nao); + } + + public void testGetter() throws Exception + { + assertNotNull(ndc.getURIs()); + assertNotNull(ndc.getPrefixes()); + assertNotNull(ndc.getPrefixes("something")); + assertNotNull(ndc.getNamespaceURI("something uri")); + } + + public void testUnsupportedOperations() throws Exception + { + try + { + ndc.registerNamespace(null, null); + fail("Should not be here"); + } + catch (UnsupportedOperationException expected) + { + // + } + + try + { + ndc.unregisterNamespace(null); + fail("Should not be here"); + } + catch (UnsupportedOperationException expected) + { + // + } + + } + + public void testDCGetters() throws Exception + { + DictionaryComponent dc = new DictionaryComponent(); + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL6_UPDATE1_XML.getBytes()); + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + + dc.setDictionaryDAO(dictionaryDAO); + + assertNotNull(dc.getAllModels()); + assertNotNull(dc.getAllDataTypes()); + assertNotNull(dc.getAllTypes()); + assertNotNull(dc.getAllAspects()); + assertNotNull(dc.getAllAssociations()); + + assertNotNull(dc.getModel(modelName)); + assertNotNull(dc.getDataTypes(modelName)); + assertNotNull(dc.getTypes(modelName)); + assertNotNull(dc.getAspects(modelName)); + assertNotNull(dc.getAssociations(modelName)); + assertNotNull(dc.getConstraints(modelName)); + assertNotNull(dc.getProperties(modelName)); + assertNotNull(dc.getProperties(modelName, ContentModel.PROP_NAME)); + assertNotNull(dc.getAllProperties(ContentModel.PROP_NAME)); + + assertNotNull(dc.getSubTypes(ContentModel.PROP_NAME, false)); + assertNotNull(dc.getSubAspects(ContentModel.ASPECT_HIDDEN, false)); + assertNotNull(dc.getConstraints(modelName, false)); + + QName[] types = (QName[]) dc.getTypes(modelName).toArray(new QName[2]); + QName text = QName.createQName(NamespaceService.DICTIONARY_MODEL_1_0_URI, "text"); + QName testAspect = QName.createQName(modelName.getNamespaceURI(), "aspect1"); + assertTrue(types.length>0); + assertNotNull(dc.getAnonymousType(types[0], Arrays.asList(testAspect))); + assertNotNull(dc.getAnonymousType(types[0])); + assertNotNull(dc.getPropertyDefs(testAspect)); + + DataTypeDefinition dataTypeDefinition = dc.getDataType(text); + assertEquals(dataTypeDefinition, dc.getDataType(Class.forName(dataTypeDefinition.getJavaClassName()))); + } + + public void testMessageLookup() throws Exception + { + DictionaryComponent dc = new DictionaryComponent(); + dc.setDictionaryDAO(dictionaryDAO); + dc.setMessageLookup(new StaticMessageLookup()); + + assertNull(dc.getMessage("fred")); + assertNull(dc.getMessage("fred", Locale.getDefault())); + assertNull(dc.getMessage("fred","cat")); + assertNull(dc.getMessage("fred", Locale.getDefault(), "dog")); + + } + + public void testLifeCycle() throws Exception + { + DictionaryComponent dc = new DictionaryComponent(); + dc.setDictionaryDAO(dictionaryDAO); + dc.init(); + dc.onEnableTenant(); + dc.onDisableTenant(); + dc.destroy(); + dc.init(); + } +} \ No newline at end of file diff --git a/data-model/src/test/java/org/alfresco/repo/dictionary/DictionaryDAOTest.java b/data-model/src/test/java/org/alfresco/repo/dictionary/DictionaryDAOTest.java new file mode 100644 index 0000000000..5ba4728665 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/dictionary/DictionaryDAOTest.java @@ -0,0 +1,1167 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.alfresco.repo.dictionary.constraint.ListOfValuesConstraint; +import org.alfresco.repo.dictionary.constraint.RegexConstraint; +import org.alfresco.repo.dictionary.constraint.RegisteredConstraint; +import org.alfresco.repo.dictionary.constraint.StringLengthConstraint; +import org.alfresco.repo.i18n.StaticMessageLookup; +import org.alfresco.repo.tenant.SingleTServiceImpl; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.service.cmr.dictionary.AssociationDefinition; +import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition; +import org.alfresco.service.cmr.dictionary.ClassDefinition; +import org.alfresco.service.cmr.dictionary.Constraint; +import org.alfresco.service.cmr.dictionary.ConstraintDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.ModelDefinition; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.namespace.NamespaceException; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.DynamicallySizedThreadPoolExecutor; +import org.alfresco.util.TraceableThreadFactory; +import org.alfresco.util.cache.DefaultAsynchronouslyRefreshedCacheRegistry; +import org.junit.Before; +import org.junit.Test; +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * + * @author sglover + * + */ +public class DictionaryDAOTest +{ + public static final String TEST_RESOURCE_MESSAGES = "alfresco/messages/dictionary-messages"; + + private static final String TEST_URL = "http://www.alfresco.org/test/dictionarydaotest/1.0"; + private static final String TEST2_URL = "http://www.alfresco.org/test/dictionarydaotest2/1.0"; + private static final String TEST_MODEL = "org/alfresco/repo/dictionary/dictionarydaotest_model.xml"; + private static final String TEST_NS_CLASH_MODEL = "org/alfresco/repo/dictionary/nstest_model.xml"; + private static final String TEST_BUNDLE = "org/alfresco/repo/dictionary/dictionarydaotest_model"; + private static final String TEST_COMMON_NS_PARENT_MODEL = "org/alfresco/repo/dictionary/commonpropertynsparent_model.xml"; + private static final String TEST_COMMON_NS_CHILD_MODEL = "org/alfresco/repo/dictionary/commonpropertynschild_model.xml"; + + private DictionaryService service; + private DictionaryDAOImpl dictionaryDAO ; + + @Before + public void setUp() throws Exception + { + // register resource bundles for messages + I18NUtil.registerResourceBundle(TEST_RESOURCE_MESSAGES); + + // Instantiate Dictionary Service + TenantService tenantService = new SingleTServiceImpl(); + + this.dictionaryDAO = new DictionaryDAOImpl(); + dictionaryDAO.setTenantService(tenantService); + initDictionaryCaches(dictionaryDAO, tenantService); + + // Populate with appropriate models + DictionaryBootstrap bootstrap = new DictionaryBootstrap(); + List bootstrapModels = new ArrayList(); + bootstrapModels.add("alfresco/model/dictionaryModel.xml"); + bootstrapModels.add(TEST_MODEL); + List labels = new ArrayList(); + labels.add(TEST_BUNDLE); + bootstrap.setModels(bootstrapModels); + bootstrap.setLabels(labels); + bootstrap.setDictionaryDAO(dictionaryDAO); + bootstrap.setTenantService(tenantService); + bootstrap.bootstrap(); + + DictionaryComponent component = new DictionaryComponent(); + component.setDictionaryDAO(dictionaryDAO); + component.setMessageLookup(new StaticMessageLookup()); + service = component; + } + + private void initDictionaryCaches(DictionaryDAOImpl dictionaryDAO, TenantService tenantService) + { + CompiledModelsCache compiledModelsCache = new CompiledModelsCache(); + compiledModelsCache.setDictionaryDAO(dictionaryDAO); + compiledModelsCache.setTenantService(tenantService); + compiledModelsCache.setRegistry(new DefaultAsynchronouslyRefreshedCacheRegistry()); + TraceableThreadFactory threadFactory = new TraceableThreadFactory(); + threadFactory.setThreadDaemon(true); + threadFactory.setThreadPriority(Thread.NORM_PRIORITY); + + ThreadPoolExecutor threadPoolExecutor = new DynamicallySizedThreadPoolExecutor(20, 20, 90, TimeUnit.SECONDS, new LinkedBlockingQueue(), threadFactory, + new ThreadPoolExecutor.CallerRunsPolicy()); + compiledModelsCache.setThreadPoolExecutor(threadPoolExecutor); + dictionaryDAO.setDictionaryRegistryCache(compiledModelsCache); + dictionaryDAO.init(); + } + + @Test + public void testBootstrap() + { + TenantService tenantService = new SingleTServiceImpl(); + + DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(); + dictionaryDAO.setTenantService(tenantService); + initDictionaryCaches(dictionaryDAO, tenantService); + + DictionaryBootstrap bootstrap = new DictionaryBootstrap(); + List bootstrapModels = new ArrayList(); + + bootstrapModels.add("alfresco/model/dictionaryModel.xml"); + + bootstrap.setModels(bootstrapModels); + bootstrap.setDictionaryDAO(dictionaryDAO); + bootstrap.setTenantService(tenantService); + bootstrap.bootstrap(); + } + + /** + * ACE-5120: Dictionary should not allow duplication of namespace prefixes + */ + @Test + public void testNamespaceClashResultsInSensibleError() + { + TenantService tenantService = new SingleTServiceImpl(); + + DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(); + dictionaryDAO.setTenantService(tenantService); + initDictionaryCaches(dictionaryDAO, tenantService); + + DictionaryBootstrap bootstrap = new DictionaryBootstrap(); + List bootstrapModels = new ArrayList(); + + bootstrapModels.add("alfresco/model/dictionaryModel.xml"); + bootstrapModels.add(TEST_MODEL); + bootstrapModels.add(TEST_NS_CLASH_MODEL); + + bootstrap.setModels(bootstrapModels); + bootstrap.setDictionaryDAO(dictionaryDAO); + bootstrap.setTenantService(tenantService); + + try + { + bootstrap.bootstrap(); + fail("Expected "+NamespaceException.class.getName()+" to be thrown, but it was not."); + } + catch (NamespaceException e) + { + System.out.println(e.getMessage()); + // Good! + } + } + + @Test + public void testUseImportedNamespaces() + { + TenantService tenantService = new SingleTServiceImpl(); + + DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(); + dictionaryDAO.setTenantService(tenantService); + initDictionaryCaches(dictionaryDAO, tenantService); + + DictionaryBootstrap bootstrap = new DictionaryBootstrap(); + List bootstrapModels = new ArrayList(); + + bootstrapModels.add("alfresco/model/dictionaryModel.xml"); + bootstrapModels.add(TEST_COMMON_NS_PARENT_MODEL); + bootstrapModels.add(TEST_COMMON_NS_CHILD_MODEL); + + bootstrap.setModels(bootstrapModels); + bootstrap.setDictionaryDAO(dictionaryDAO); + bootstrap.setTenantService(tenantService); + bootstrap.bootstrap(); + } + + @Test + public void testLabels() + { + QName model = QName.createQName(TEST_URL, "dictionarydaotest"); + ModelDefinition modelDef = service.getModel(model); + assertEquals("Model Description", modelDef.getDescription(service)); + + QName type = QName.createQName(TEST_URL, "base"); + TypeDefinition typeDef = service.getType(type); + assertEquals("Base Title", typeDef.getTitle(service)); + assertEquals("Base Description", typeDef.getDescription(service)); + + QName prop = QName.createQName(TEST_URL, "prop1"); + PropertyDefinition propDef = service.getProperty(prop); + assertEquals("Prop1 Title", propDef.getTitle(service)); + assertEquals("Prop1 Description", propDef.getDescription(service)); + + QName assoc = QName.createQName(TEST_URL, "assoc1"); + AssociationDefinition assocDef = service.getAssociation(assoc); + assertEquals("Assoc1 Title", assocDef.getTitle(service)); + assertEquals("Assoc1 Description", assocDef.getDescription(service)); + + QName datatype = QName.createQName(TEST_URL, "datatype"); + DataTypeDefinition datatypeDef = service.getDataType(datatype); + assertEquals("alfresco/model/dataTypeAnalyzers", datatypeDef.getAnalyserResourceBundleName()); + + QName constraint = QName.createQName(TEST_URL, "list1"); + ConstraintDefinition constraintDef = service.getConstraint(constraint); + assertEquals("List1 title", constraintDef.getTitle(service)); + assertEquals("List1 description", constraintDef.getDescription(service)); + + + // Localisation of List Of Values Constraint. + // 1. LoV defined at the top of the model. + ListOfValuesConstraint lovConstraint = (ListOfValuesConstraint)constraintDef.getConstraint(); + assertEquals("Wrong localised lov value.", "ABC display", lovConstraint.getDisplayLabel("ABC", service)); + assertEquals("Wrong localised lov value.", "DEF display", lovConstraint.getDisplayLabel("DEF", service)); + assertEquals("Wrong localised lov value.", "VALUE WITH SPACES display", lovConstraint.getDisplayLabel("VALUE WITH SPACES", service)); // Keys with spaces. + assertEquals("Wrong localised lov value.", "VALUE WITH TRAILING SPACE display", lovConstraint.getDisplayLabel("VALUE WITH TRAILING SPACE ", service)); // Keys with trailing space. + assertNull(lovConstraint.getDisplayLabel("nosuchLOV", service)); + + // 2. A named LoV defined within a specific property "non-Ref". + QName constrainedPropName = QName.createQName(TEST_URL, "constrainedProp"); + PropertyDefinition constrainedPropDef = service.getProperty(constrainedPropName); + List constraints = constrainedPropDef.getConstraints(); + assertEquals("Wrong number of constraints.", 1, constraints.size()); + ConstraintDefinition inlineConstraintDef = constraints.get(0); + lovConstraint = (ListOfValuesConstraint)inlineConstraintDef.getConstraint(); + assertEquals("Wrong localised lov value.", "ALPHA display", lovConstraint.getDisplayLabel("ALPHA", service)); + assertEquals("Wrong localised lov value.", "BETA display", lovConstraint.getDisplayLabel("BETA", service)); + assertEquals("Wrong localised lov value.", "GAMMA, DELTA display", lovConstraint.getDisplayLabel("GAMMA, DELTA", service)); // Keys with commas + assertEquals("Wrong localised lov value.", "OMEGA", lovConstraint.getDisplayLabel("OMEGA", service)); + assertNull(lovConstraint.getDisplayLabel("nosuchLOV", service)); + + // Localisation of unnamed LoV defined within a specific property are not supported. + } + + @Test + public void testConstraints() + { + QName model = QName.createQName(TEST_URL, "dictionarydaotest"); + Collection modelConstraints = service.getConstraints(model); + assertEquals(23, modelConstraints.size()); // 10 + 7 + 6 + + QName conRegExp1QName = QName.createQName(TEST_URL, "regex1"); + boolean found1 = false; + + QName conStrLen1QName = QName.createQName(TEST_URL, "stringLength1"); + boolean found2 = false; + + for (ConstraintDefinition constraintDef : modelConstraints) + { + if (constraintDef.getName().equals(conRegExp1QName)) + { + assertEquals("Regex1 title", constraintDef.getTitle(service)); + assertEquals("Regex1 description", constraintDef.getDescription(service)); + found1 = true; + } + + if (constraintDef.getName().equals(conStrLen1QName)) + { + assertNull(constraintDef.getTitle(service)); + assertNull(constraintDef.getDescription(service)); + found2 = true; + } + } + assertTrue(found1); + assertTrue(found2); + + // get the constraints for a property without constraints + QName propNoConstraintsQName = QName.createQName(TEST_URL, "fileprop"); + PropertyDefinition propNoConstraintsDef = service.getProperty(propNoConstraintsQName); + assertNotNull("Property without constraints returned null list", propNoConstraintsDef.getConstraints()); + + // get the constraints defined for the property + QName prop1QName = QName.createQName(TEST_URL, "prop1"); + PropertyDefinition propDef = service.getProperty(prop1QName); + List constraints = propDef.getConstraints(); + assertNotNull("Null constraints list", constraints); + assertEquals("Incorrect number of constraints", 3, constraints.size()); + assertTrue("Constraint instance incorrect", constraints.get(0).getConstraint() instanceof RegexConstraint); + assertTrue("Constraint instance incorrect", constraints.get(1).getConstraint() instanceof StringLengthConstraint); + assertTrue("Constraint instance incorrect", constraints.get(2).getConstraint() instanceof RegisteredConstraint); + + // check the individual constraints + ConstraintDefinition constraintDef = constraints.get(0); + assertTrue("Constraint anonymous name incorrect", constraintDef.getName().getLocalName().equals("dictionarydaotest_base_prop1_anon_0")); + + // inherit title / description for reference constraint + assertTrue("Constraint title incorrect", constraintDef.getTitle(service).equals("Regex1 title")); + assertTrue("Constraint description incorrect", constraintDef.getDescription(service).equals("Regex1 description")); + + constraintDef = constraints.get(1); + assertTrue("Constraint anonymous name incorrect", constraintDef.getName().getLocalName().equals("dictionarydaotest_base_prop1_anon_1")); + + assertTrue("Constraint title incorrect", constraintDef.getTitle(service).equals("Prop1 Strlen1 title")); + assertTrue("Constraint description incorrect", constraintDef.getDescription(service).equals("Prop1 Strlen1 description")); + + // check that the constraint implementation is valid (it used a reference) + Constraint constraint = constraintDef.getConstraint(); + assertNotNull("Reference constraint has no implementation", constraint); + } + + @Test + public void testConstraintsOverrideInheritance() + { + QName baseQName = QName.createQName(TEST_URL, "base"); + QName fileQName = QName.createQName(TEST_URL, "file"); + QName folderQName = QName.createQName(TEST_URL, "folder"); + QName prop1QName = QName.createQName(TEST_URL, "prop1"); + + // get the base property + PropertyDefinition prop1Def = service.getProperty(baseQName, prop1QName); + assertNotNull(prop1Def); + List prop1Constraints = prop1Def.getConstraints(); + assertEquals("Incorrect number of constraints", 3, prop1Constraints.size()); + assertTrue("Constraint instance incorrect", prop1Constraints.get(0).getConstraint() instanceof RegexConstraint); + assertTrue("Constraint instance incorrect", prop1Constraints.get(1).getConstraint() instanceof StringLengthConstraint); + assertTrue("Constraint instance incorrect", prop1Constraints.get(2).getConstraint() instanceof RegisteredConstraint); + + // check the inherited property on folder (must be same as above) + prop1Def = service.getProperty(folderQName, prop1QName); + assertNotNull(prop1Def); + prop1Constraints = prop1Def.getConstraints(); + assertEquals("Incorrect number of constraints", 3, prop1Constraints.size()); + assertTrue("Constraint instance incorrect", prop1Constraints.get(0).getConstraint() instanceof RegexConstraint); + assertTrue("Constraint instance incorrect", prop1Constraints.get(1).getConstraint() instanceof StringLengthConstraint); + assertTrue("Constraint instance incorrect", prop1Constraints.get(2).getConstraint() instanceof RegisteredConstraint); + + // check the overridden property on file (must be reverse of above) + prop1Def = service.getProperty(fileQName, prop1QName); + assertNotNull(prop1Def); + prop1Constraints = prop1Def.getConstraints(); + assertEquals("Incorrect number of constraints", 3, prop1Constraints.size()); + assertTrue("Constraint instance incorrect", prop1Constraints.get(0).getConstraint() instanceof StringLengthConstraint); + assertTrue("Constraint instance incorrect", prop1Constraints.get(1).getConstraint() instanceof RegexConstraint); + assertTrue("Constraint instance incorrect", prop1Constraints.get(2).getConstraint() instanceof RegisteredConstraint); + } + + @Test + public void testConstraintsOverrideInheritanceOnAspects() + { + QName aspectBaseQName = QName.createQName(TEST_URL, "aspect-base"); + QName aspectOneQName = QName.createQName(TEST_URL, "aspect-one"); + QName aspectTwoQName = QName.createQName(TEST_URL, "aspect-two"); + QName aspectThreeQName = QName.createQName(TEST2_URL, "aspect-three"); + QName propQName = QName.createQName(TEST_URL, "aspect-base-p1"); + + // get the base property + PropertyDefinition propDef = service.getProperty(aspectBaseQName, propQName); + assertNotNull(propDef); + List propConstraints = propDef.getConstraints(); + assertEquals("Incorrect number of constraints", 1, propConstraints.size()); + assertTrue("Constraint instance incorrect", propConstraints.get(0).getConstraint() instanceof ListOfValuesConstraint); + ListOfValuesConstraint constraint = (ListOfValuesConstraint) propConstraints.get(0).getConstraint(); + List allowedValues = constraint.getAllowedValues(); + assertEquals("Expected 4 allowed values", 4, allowedValues.size()); + assertEquals("ABC", allowedValues.get(0)); + assertEquals("DEF", allowedValues.get(1)); + assertEquals("VALUE WITH SPACES", allowedValues.get(2)); + assertEquals("VALUE WITH TRAILING SPACE ", allowedValues.get(3)); + + // check the inherited property on first derived aspect + propDef = service.getProperty(aspectOneQName, propQName); + assertNotNull(propDef); + propConstraints = propDef.getConstraints(); + assertEquals("Incorrect number of constraints", 1, propConstraints.size()); + assertTrue("Constraint instance incorrect", propConstraints.get(0).getConstraint() instanceof ListOfValuesConstraint); + constraint = (ListOfValuesConstraint) propConstraints.get(0).getConstraint(); + allowedValues = constraint.getAllowedValues(); + assertEquals("Expected 1 allowed values", 1, allowedValues.size()); + assertEquals("HIJ", allowedValues.get(0)); + + // check the inherited property on second derived aspect + propDef = service.getProperty(aspectTwoQName, propQName); + assertNotNull(propDef); + propConstraints = propDef.getConstraints(); + assertEquals("Incorrect number of constraints", 2, propConstraints.size()); + assertTrue("Constraint instance incorrect", propConstraints.get(0).getConstraint() instanceof ListOfValuesConstraint); + assertTrue("Constraint instance incorrect", propConstraints.get(1).getConstraint() instanceof ListOfValuesConstraint); + constraint = (ListOfValuesConstraint) propConstraints.get(0).getConstraint(); + allowedValues = constraint.getAllowedValues(); + assertEquals("Wrong number of allowed values", 4, allowedValues.size()); + assertEquals("ABC", allowedValues.get(0)); + assertEquals("DEF", allowedValues.get(1)); + assertEquals("VALUE WITH SPACES", allowedValues.get(2)); + assertEquals("VALUE WITH TRAILING SPACE ", allowedValues.get(3)); + constraint = (ListOfValuesConstraint) propConstraints.get(1).getConstraint(); + allowedValues = constraint.getAllowedValues(); + assertEquals("Wrong number of allowed values", 1, allowedValues.size()); + assertEquals("HIJ", allowedValues.get(0)); + + // check the cross-namespace inheritance + propDef = service.getProperty(aspectThreeQName, propQName); + assertNotNull(propDef); + propConstraints = propDef.getConstraints(); + assertEquals("Incorrect number of constraints", 1, propConstraints.size()); + assertTrue("Constraint instance incorrect", propConstraints.get(0).getConstraint() instanceof ListOfValuesConstraint); + constraint = (ListOfValuesConstraint) propConstraints.get(0).getConstraint(); + allowedValues = constraint.getAllowedValues(); + assertEquals("Expected 1 allowed values", 1, allowedValues.size()); + assertEquals("XYZ", allowedValues.get(0)); + } + + @Test + public void testArchive() + { + QName testFileQName = QName.createQName(TEST_URL, "file"); + ClassDefinition fileClassDef = service.getClass(testFileQName); + assertTrue("File type should have the archive flag", fileClassDef.getArchive()); + + QName testFileDerivedQName = QName.createQName(TEST_URL, "file-derived"); + ClassDefinition fileDerivedClassDef = service.getClass(testFileDerivedQName); + assertTrue("Direct derived File type should have the archive flag", fileDerivedClassDef.getArchive()); + + QName testFileDerivedNoArchiveQName = QName.createQName(TEST_URL, "file-derived-no-archive"); + ClassDefinition fileDerivedNoArchiveClassDef = service.getClass(testFileDerivedNoArchiveQName); + assertFalse("Derived File with archive override type should NOT have the archive flag", + fileDerivedNoArchiveClassDef.getArchive()); + + QName testFolderQName = QName.createQName(TEST_URL, "folder"); + ClassDefinition folderClassDef = service.getClass(testFolderQName); + assertNull("Folder type should not have the archive flag", folderClassDef.getArchive()); + } + + @Test + public void testMandatoryEnforced() + { + // get the properties for the test type + QName testEnforcedQName = QName.createQName(TEST_URL, "enforced"); + ClassDefinition testEnforcedClassDef = service.getClass(testEnforcedQName); + Map testEnforcedPropertyDefs = testEnforcedClassDef.getProperties(); + + PropertyDefinition propertyDef = null; + + QName testMandatoryEnforcedQName = QName.createQName(TEST_URL, "mandatory-enforced"); + propertyDef = testEnforcedPropertyDefs.get(testMandatoryEnforcedQName); + assertNotNull("Property not found: " + testMandatoryEnforcedQName, + propertyDef); + assertTrue("Expected property to be mandatory: " + testMandatoryEnforcedQName, + propertyDef.isMandatory()); + assertTrue("Expected property to be mandatory-enforced: " + testMandatoryEnforcedQName, + propertyDef.isMandatoryEnforced()); + + QName testMandatoryNotEnforcedQName = QName.createQName(TEST_URL, "mandatory-not-enforced"); + propertyDef = testEnforcedPropertyDefs.get(testMandatoryNotEnforcedQName); + assertNotNull("Property not found: " + testMandatoryNotEnforcedQName, + propertyDef); + assertTrue("Expected property to be mandatory: " + testMandatoryNotEnforcedQName, + propertyDef.isMandatory()); + assertFalse("Expected property to be mandatory-not-enforced: " + testMandatoryNotEnforcedQName, + propertyDef.isMandatoryEnforced()); + + QName testMandatoryDefaultEnforcedQName = QName.createQName(TEST_URL, "mandatory-default-enforced"); + propertyDef = testEnforcedPropertyDefs.get(testMandatoryDefaultEnforcedQName); + assertNotNull("Property not found: " + testMandatoryDefaultEnforcedQName, + propertyDef); + assertTrue("Expected property to be mandatory: " + testMandatoryDefaultEnforcedQName, + propertyDef.isMandatory()); + assertFalse("Expected property to be mandatory-not-enforced: " + testMandatoryDefaultEnforcedQName, + propertyDef.isMandatoryEnforced()); + } + + @Test + public void testSubClassOf() + { + QName invalid = QName.createQName(TEST_URL, "invalid"); + QName base = QName.createQName(TEST_URL, "base"); + QName file = QName.createQName(TEST_URL, "file"); + QName folder = QName.createQName(TEST_URL, "folder"); + QName referenceable = QName.createQName(TEST_URL, "referenceable"); + + // Test invalid args + boolean testI1 = service.isSubClass(invalid, referenceable); + + assertFalse(testI1); + + boolean testI2 = service.isSubClass(referenceable, invalid); + assertFalse(testI2); + + boolean testI3 = service.isSubClass(invalid, invalid); + assertFalse(testI3); + + // Test various flavours of subclassof + boolean test1 = service.isSubClass(file, referenceable); // type vs aspect + assertFalse(test1); + boolean test2 = service.isSubClass(file, folder); // seperate hierarchies + assertFalse(test2); + boolean test3 = service.isSubClass(file, file); // self + assertTrue(test3); + boolean test4 = service.isSubClass(folder, base); // subclass + assertTrue(test4); + boolean test5 = service.isSubClass(base, folder); // reversed test + assertFalse(test5); + } + + @Test + public void testPropertyOverride() + { + TypeDefinition type1 = service.getType(QName.createQName(TEST_URL, "overridetype1")); + Map props1 = type1.getProperties(); + PropertyDefinition prop1 = props1.get(QName.createQName(TEST_URL, "propoverride")); + String def1 = prop1.getDefaultValue(); + assertEquals("one", def1); + + TypeDefinition type2 = service.getType(QName.createQName(TEST_URL, "overridetype2")); + Map props2 = type2.getProperties(); + PropertyDefinition prop2 = props2.get(QName.createQName(TEST_URL, "propoverride")); + String def2 = prop2.getDefaultValue(); + assertEquals("two", def2); + + TypeDefinition type3 = service.getType(QName.createQName(TEST_URL, "overridetype3")); + Map props3 = type3.getProperties(); + PropertyDefinition prop3 = props3.get(QName.createQName(TEST_URL, "propoverride")); + String def3 = prop3.getDefaultValue(); + assertEquals("three", def3); + } + + @Test + public void testChildAssocPropagate() + { + // Check the default value + AssociationDefinition assocDef = service.getAssociation(QName.createQName(TEST_URL, "childassoc1")); + assertNotNull("No such child association found", assocDef); + assertTrue("Expected a child association", assocDef instanceof ChildAssociationDefinition); + ChildAssociationDefinition childAssocDef = (ChildAssociationDefinition) assocDef; + assertFalse("Expected 'false' for default timestamp propagation", childAssocDef.getPropagateTimestamps()); + + // Check the explicit value + assocDef = service.getAssociation(QName.createQName(TEST_URL, "childassocPropagate")); + assertNotNull("No such child association found", assocDef); + assertTrue("Expected a child association", assocDef instanceof ChildAssociationDefinition); + childAssocDef = (ChildAssociationDefinition) assocDef; + assertTrue("Expected 'true' for timestamp propagation", childAssocDef.getPropagateTimestamps()); + } + + @Test + public void testDataTypeAnlyserResolution() + { + // Stuff to configure/ + + TenantService tenantService = new SingleTServiceImpl(); + + DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(); + dictionaryDAO.setTenantService(tenantService); + initDictionaryCaches(dictionaryDAO, tenantService); + + ModelDefinition modelDefinition; + DataTypeDefinition dataTypeDefinition; + + // + + dictionaryDAO.putModel(createModel(dictionaryDAO, false, false, false)); + QName modeQName = QName.createQName("test:analyzerModel", dictionaryDAO); + QName dataTypeQName = QName.createQName("test:analyzerDataType", dictionaryDAO); + + modelDefinition = dictionaryDAO.getModel(modeQName); + assertEquals(modelDefinition.getAnalyserResourceBundleName(), null); + dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName); + assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), null); + assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), null); + + assertNull(dataTypeDefinition.resolveAnalyserClassName()); + dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle"); + try + { + dataTypeDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("defaultBundle")); + } + + dictionaryDAO.setDefaultAnalyserResourceBundleName(null); + dictionaryDAO.removeModel(modeQName); + + // + + dictionaryDAO.putModel(createModel(dictionaryDAO, false, false, true)); + + modelDefinition = dictionaryDAO.getModel(modeQName); + assertEquals(modelDefinition.getAnalyserResourceBundleName(), null); + dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName); + assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), null); + assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), "java.lang.String"); + + assertEquals(dataTypeDefinition.resolveAnalyserClassName(), "java.lang.String"); + dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle"); + try + { + dataTypeDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("defaultBundle")); + } + + dictionaryDAO.setDefaultAnalyserResourceBundleName(null); + dictionaryDAO.removeModel(modeQName); + + // + + dictionaryDAO.putModel(createModel(dictionaryDAO, false, true, false)); + + modelDefinition = dictionaryDAO.getModel(modeQName); + assertEquals(modelDefinition.getAnalyserResourceBundleName(), null); + dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName); + assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), "dataTypeResourceBundle"); + assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), null); + + try + { + dataTypeDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("dataTypeResourceBundle")); + } + dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle"); + try + { + dataTypeDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("defaultBundle")); + } + + dictionaryDAO.setDefaultAnalyserResourceBundleName(null); + dictionaryDAO.removeModel(modeQName); + + // + + dictionaryDAO.putModel(createModel(dictionaryDAO, false, true, true)); + + modelDefinition = dictionaryDAO.getModel(modeQName); + assertEquals(modelDefinition.getAnalyserResourceBundleName(), null); + dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName); + assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), "dataTypeResourceBundle"); + assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), "java.lang.String"); + + try + { + dataTypeDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("dataTypeResourceBundle")); + } + dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle"); + try + { + dataTypeDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("defaultBundle")); + } + + dictionaryDAO.setDefaultAnalyserResourceBundleName(null); + dictionaryDAO.removeModel(modeQName); + + dictionaryDAO.putModel(createModel(dictionaryDAO, true, false, false)); + + + modelDefinition = dictionaryDAO.getModel(modeQName); + assertEquals(modelDefinition.getAnalyserResourceBundleName(), "dataTypeModelResourceBundle"); + dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName); + assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), null); + assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), null); + + try + { + dataTypeDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("dataTypeModelResourceBundle")); + } + dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle"); + try + { + dataTypeDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("defaultBundle")); + } + + dictionaryDAO.setDefaultAnalyserResourceBundleName(null); + dictionaryDAO.removeModel(modeQName); + + // + + dictionaryDAO.putModel(createModel(dictionaryDAO, true, false, true)); + + modelDefinition = dictionaryDAO.getModel(modeQName); + assertEquals(modelDefinition.getAnalyserResourceBundleName(), "dataTypeModelResourceBundle"); + dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName); + assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), null); + assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), "java.lang.String"); + + try + { + dataTypeDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("dataTypeModelResourceBundle")); + } + dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle"); + try + { + dataTypeDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("defaultBundle")); + } + + dictionaryDAO.setDefaultAnalyserResourceBundleName(null); + dictionaryDAO.removeModel(modeQName); + + // + + dictionaryDAO.putModel(createModel(dictionaryDAO, true, true, false)); + + modelDefinition = dictionaryDAO.getModel(modeQName); + assertEquals(modelDefinition.getAnalyserResourceBundleName(), "dataTypeModelResourceBundle"); + dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName); + assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), "dataTypeResourceBundle"); + assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), null); + + try + { + dataTypeDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("dataTypeResourceBundle")); + } + dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle"); + try + { + dataTypeDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("defaultBundle")); + } + + dictionaryDAO.setDefaultAnalyserResourceBundleName(null); + dictionaryDAO.removeModel(modeQName); + + // + + dictionaryDAO.putModel(createModel(dictionaryDAO, true, true, true)); + + modelDefinition = dictionaryDAO.getModel(modeQName); + assertEquals(modelDefinition.getAnalyserResourceBundleName(), "dataTypeModelResourceBundle"); + dataTypeDefinition = dictionaryDAO.getDataType(dataTypeQName); + assertEquals(dataTypeDefinition.getAnalyserResourceBundleName(), "dataTypeResourceBundle"); + assertEquals(dataTypeDefinition.getDefaultAnalyserClassName(), "java.lang.String"); + + try + { + dataTypeDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("dataTypeResourceBundle")); + } + dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle"); + try + { + dataTypeDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("defaultBundle")); + } + + dictionaryDAO.setDefaultAnalyserResourceBundleName(null); + dictionaryDAO.removeModel(modeQName); + } + + private M2Model createModel(DictionaryDAO dictionaryDAO, boolean withModelBundle, boolean withDataTypeBundle, boolean withTypeAnalyserClss) + { + String testNamespace = "http://www.alfresco.org/test/analyserResolution"; + M2Model model = M2Model.createModel("test:analyzerModel"); + model.createNamespace(testNamespace, "test"); + if(withModelBundle) + { + model.setAnalyserResourceBundleName("dataTypeModelResourceBundle"); + } + + M2DataType dataTypeWithAnalyserBundleName = model.createPropertyType("test:analyzerDataType"); + dataTypeWithAnalyserBundleName.setJavaClassName("java.lang.String"); + if(withTypeAnalyserClss) + { + dataTypeWithAnalyserBundleName.setDefaultAnalyserClassName("java.lang.String"); + } + if(withDataTypeBundle) + { + dataTypeWithAnalyserBundleName.setAnalyserResourceBundleName("dataTypeResourceBundle"); + } + return model; + } + + @Test + public void testTypeAnalyserResolution() + { + // Stuff to configure/ + + TenantService tenantService = new SingleTServiceImpl(); + + DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(); + dictionaryDAO.setTenantService(tenantService); + initDictionaryCaches(dictionaryDAO, tenantService); + + // build data model - typical settings + dictionaryDAO.putModel(createModel(dictionaryDAO, true, false, true)); + + // check simple stack - all defined keep removing the end + + ModelDefinition modelDefinition; + ClassDefinition superDefinition; + ClassDefinition classDefinition; + PropertyDefinition propertyDefinition; + + dictionaryDAO.putModel(createTypeModel(dictionaryDAO, true, true, true, true)); + + QName modelQName = QName.createQName("test2:analyzerClassModel", dictionaryDAO); + QName superQName = QName.createQName("test2:analyzerSuperType", dictionaryDAO); + QName typeQName = QName.createQName("test2:analyzerType", dictionaryDAO); + QName propertyQName = QName.createQName("test2:analyzerProperty", dictionaryDAO); + + modelDefinition = dictionaryDAO.getModel(modelQName); + assertEquals(modelDefinition.getAnalyserResourceBundleName(), "typeModelResourceBundle"); + superDefinition = dictionaryDAO.getType(superQName); + assertEquals(superDefinition.getAnalyserResourceBundleName(), "superTypeResourceBundle"); + classDefinition = dictionaryDAO.getType(typeQName); + assertEquals(classDefinition.getAnalyserResourceBundleName(), "typeResourceBundle"); + propertyDefinition = dictionaryDAO.getProperty(propertyQName); + assertEquals(propertyDefinition.getAnalyserResourceBundleName(), "propertyResourceBundle"); + + try + { + propertyDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("propertyResourceBundle")); + } + dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle"); + try + { + propertyDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("propertyResourceBundle")); + } + + dictionaryDAO.setDefaultAnalyserResourceBundleName(null); + dictionaryDAO.removeModel(modelQName); + + // + + dictionaryDAO.putModel(createTypeModel(dictionaryDAO, true, true, true, false)); + + modelDefinition = dictionaryDAO.getModel(modelQName); + assertEquals(modelDefinition.getAnalyserResourceBundleName(), "typeModelResourceBundle"); + superDefinition = dictionaryDAO.getType(superQName); + assertEquals(superDefinition.getAnalyserResourceBundleName(), "superTypeResourceBundle"); + classDefinition = dictionaryDAO.getType(typeQName); + assertEquals(classDefinition.getAnalyserResourceBundleName(), "typeResourceBundle"); + propertyDefinition = dictionaryDAO.getProperty(propertyQName); + assertEquals(propertyDefinition.getAnalyserResourceBundleName(), null); + + try + { + propertyDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("typeResourceBundle")); + } + dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle"); + try + { + propertyDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("typeResourceBundle")); + } + + dictionaryDAO.setDefaultAnalyserResourceBundleName(null); + dictionaryDAO.removeModel(modelQName); + +// + + dictionaryDAO.putModel(createTypeModel(dictionaryDAO, true, true, false, false)); + + modelDefinition = dictionaryDAO.getModel(modelQName); + assertEquals(modelDefinition.getAnalyserResourceBundleName(), "typeModelResourceBundle"); + superDefinition = dictionaryDAO.getType(superQName); + assertEquals(superDefinition.getAnalyserResourceBundleName(), "superTypeResourceBundle"); + classDefinition = dictionaryDAO.getType(typeQName); + assertEquals(classDefinition.getAnalyserResourceBundleName(), null); + propertyDefinition = dictionaryDAO.getProperty(propertyQName); + assertEquals(propertyDefinition.getAnalyserResourceBundleName(), null); + + try + { + propertyDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("superTypeResourceBundle")); + } + dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle"); + try + { + propertyDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("superTypeResourceBundle")); + } + + dictionaryDAO.setDefaultAnalyserResourceBundleName(null); + dictionaryDAO.removeModel(modelQName); + +// + + dictionaryDAO.putModel(createTypeModel(dictionaryDAO, true, false, false, false)); + + modelDefinition = dictionaryDAO.getModel(modelQName); + assertEquals(modelDefinition.getAnalyserResourceBundleName(), "typeModelResourceBundle"); + superDefinition = dictionaryDAO.getType(superQName); + assertEquals(superDefinition.getAnalyserResourceBundleName(), null); + classDefinition = dictionaryDAO.getType(typeQName); + assertEquals(classDefinition.getAnalyserResourceBundleName(), null); + propertyDefinition = dictionaryDAO.getProperty(propertyQName); + assertEquals(propertyDefinition.getAnalyserResourceBundleName(), null); + + try + { + propertyDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("typeModelResourceBundle")); + } + dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle"); + try + { + propertyDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("typeModelResourceBundle")); + } + + dictionaryDAO.setDefaultAnalyserResourceBundleName(null); + dictionaryDAO.removeModel(modelQName); + +// + + dictionaryDAO.putModel(createTypeModel(dictionaryDAO, false, false, false, false)); + + modelDefinition = dictionaryDAO.getModel(modelQName); + assertEquals(modelDefinition.getAnalyserResourceBundleName(), null); + superDefinition = dictionaryDAO.getType(superQName); + assertEquals(superDefinition.getAnalyserResourceBundleName(), null); + classDefinition = dictionaryDAO.getType(typeQName); + assertEquals(classDefinition.getAnalyserResourceBundleName(), null); + propertyDefinition = dictionaryDAO.getProperty(propertyQName); + assertEquals(propertyDefinition.getAnalyserResourceBundleName(), null); + + try + { + propertyDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("dataTypeModelResourceBundle")); + } + dictionaryDAO.setDefaultAnalyserResourceBundleName("defaultBundle"); + try + { + propertyDefinition.resolveAnalyserClassName(); + fail(); + } + catch(MissingResourceException mre) + { + assertTrue(mre.getMessage().contains("defaultBundle")); + } + + dictionaryDAO.setDefaultAnalyserResourceBundleName(null); + dictionaryDAO.removeModel(modelQName); + + + } + + /** + * @param dictionaryDAO DictionaryDAOImpl + * @param withModelBundle boolean + * @param withInheritedTypeBundle boolean + * @param withTypeBundle boolean + * @param withPropertyBundle boolean + * @return M2Model + */ + private M2Model createTypeModel(DictionaryDAOImpl dictionaryDAO, boolean withModelBundle, boolean withInheritedTypeBundle, boolean withTypeBundle, boolean withPropertyBundle) + { + String testNamespace = "http://www.alfresco.org/test/analyserResolutionType"; + M2Model model = M2Model.createModel("test2:analyzerClassModel"); + model.createNamespace(testNamespace, "test2"); + model.createImport("http://www.alfresco.org/test/analyserResolution", "test"); + if(withModelBundle) + { + model.setAnalyserResourceBundleName("typeModelResourceBundle"); + } + + M2Type superTypeWithAnalyserBundleName = model.createType("test2:analyzerSuperType"); + if(withInheritedTypeBundle) + { + superTypeWithAnalyserBundleName.setAnalyserResourceBundleName("superTypeResourceBundle"); + } + + M2Type typeWithAnalyserBundleName = model.createType("test2:analyzerType"); + typeWithAnalyserBundleName.setParentName("test2:analyzerSuperType"); + if(withTypeBundle) + { + typeWithAnalyserBundleName.setAnalyserResourceBundleName("typeResourceBundle"); + } + + M2Property propertyWithAnalyserBundelName = typeWithAnalyserBundleName.createProperty("test2:analyzerProperty"); + propertyWithAnalyserBundelName.setType("test:analyzerDataType"); + if(withPropertyBundle) + { + propertyWithAnalyserBundelName.setAnalyserResourceBundleName("propertyResourceBundle"); + } + return model; + } + + //testing a model containing circular dependency cannot be imported with bootstrap + @Test + public void testBootstrapImportModelWithCircularTypes() + { + TenantService tenantService = new SingleTServiceImpl(); + + DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(); + dictionaryDAO.setTenantService(tenantService); + initDictionaryCaches(dictionaryDAO, tenantService); + + DictionaryBootstrap bootstrap = new DictionaryBootstrap(); + List bootstrapModels = new ArrayList(); + + bootstrapModels.add("org/alfresco/repo/dictionary/modelCircularTypes.xml"); + bootstrap.setModels(bootstrapModels); + bootstrap.setDictionaryDAO(dictionaryDAO); + bootstrap.setTenantService(tenantService); + + try + { + bootstrap.bootstrap(); + fail("Bootstrap should fail as the model contains a cyclic refrence"); + } + catch(DictionaryException e) + { + assertEquals(e.getMsgId(), "d_dictionary.bootstrap.model_not_imported"); + } + } + + @Test + public void testCreateModelWithCircularTypeDependency() + { + TenantService tenantService = new SingleTServiceImpl(); + + DictionaryDAOImpl dictionaryDAO = new DictionaryDAOImpl(); + dictionaryDAO.setTenantService(tenantService); + initDictionaryCaches(dictionaryDAO, tenantService); + + //create model + String testNamespace = "http://www.alfresco.org/model/dictionary/1.0/my"; + M2Model model = M2Model.createModel("my:circularModel"); + model.createNamespace(testNamespace, "my"); + model.setAnalyserResourceBundleName("typeModelResourceBundle"); + M2Type typeA = model.createType("my:circularA"); + typeA.setParentName("my:circularC"); + M2Type typeB = model.createType("my:circularB"); + typeB.setParentName("my:circularA"); + M2Type typeC = model.createType("my:circularC"); + typeC.setParentName("my:circularB"); + + try + { + dictionaryDAO.putModel(model); + fail("Model should not be saved successfully because it contains a cyclic reference"); + } catch(DictionaryException e) + { + assertEquals(e.getMsgId(), "d_dictionary.compiled_model.err.compile.failure"); + } + } +} diff --git a/data-model/src/test/java/org/alfresco/repo/dictionary/DiffModelTest.java b/data-model/src/test/java/org/alfresco/repo/dictionary/DiffModelTest.java new file mode 100644 index 0000000000..ca5308fc73 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/dictionary/DiffModelTest.java @@ -0,0 +1,508 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary; + +import java.io.ByteArrayInputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import junit.framework.TestCase; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.tenant.SingleTServiceImpl; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.service.namespace.NamespaceException; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.DynamicallySizedThreadPoolExecutor; +import org.alfresco.util.TraceableThreadFactory; +import org.alfresco.util.cache.DefaultAsynchronouslyRefreshedCacheRegistry; + +public class DiffModelTest extends AbstractModelTest +{ + + public static final String MODEL1_DUPLICATED_XML = + "" + + + " Another description" + + " Alfresco" + + " 2007-08-01" + + " 1.0" + + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + + " " + + " Base" + + " The Base Aspect 1" + + " " + + " " + + " d:text" + + " " + + " " + + " d:int" + + " " + + " " + + " " + + + " " + + + ""; + public void testDeleteModel() + { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL1_XML.getBytes()); + + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + + CompiledModel previousVersion = dictionaryDAO.getCompiledModel(modelName); + + List modelDiffs = dictionaryDAO.diffModel(previousVersion, null); + + for (M2ModelDiff modelDiff : modelDiffs) + { + System.out.println(modelDiff.toString()); + } + + assertEquals(6, modelDiffs.size()); + + assertEquals(3, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_DELETED)); + assertEquals(3, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_DELETED)); + } + + @SuppressWarnings("unused") + public void testNoExistingModelToDelete() + { + try + { + List modelDiffs = dictionaryDAO.diffModel(null, null); + assertTrue("Should throw exeception that there is no previous version of the model to delete", true); + } + catch (AlfrescoRuntimeException e) + { + assertTrue("Wrong error message", e.getMessage().equals("Invalid arguments - no previous version of model to delete")); + } + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL1_XML.getBytes()); + + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + + CompiledModel compiledModel = dictionaryDAO.getCompiledModel(modelName); + + try + { + List modelDiffs = dictionaryDAO.diffModel(null, compiledModel); + assertTrue("Should throw exeception that there is no previous version of the model to delete", true); + } + catch (AlfrescoRuntimeException e) + { + assertTrue("Wrong error message", e.getMessage().equals("Invalid arguments - no previous version of model to delete")); + } + } + + public void testNewModel() + { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL1_XML.getBytes()); + + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + + CompiledModel newVersion = dictionaryDAO.getCompiledModel(modelName); + + List modelDiffs = dictionaryDAO.diffModel(null, newVersion); + + for (M2ModelDiff modelDiff : modelDiffs) + { + System.out.println(modelDiff.toString()); + } + + assertEquals(6, modelDiffs.size()); + + assertEquals(3, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_CREATED)); + assertEquals(3, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_CREATED)); + } + + public void testDuplicateModels() + { + ByteArrayInputStream byteArrayInputStream1 = new ByteArrayInputStream(AbstractModelTest.MODEL1_XML.getBytes()); + ByteArrayInputStream byteArrayInputStream2 = new ByteArrayInputStream(MODEL1_DUPLICATED_XML.getBytes()); + + M2Model model1 = M2Model.createModel(byteArrayInputStream1); + dictionaryDAO.putModel(model1); + + M2Model model2 = M2Model.createModel(byteArrayInputStream2); + + try + { + dictionaryDAO.putModel(model2); + fail("This model with this URI has already been defined"); + } + catch (NamespaceException exception) + { + // Ignore since we where expecting this + } + } + + public void testNonIncUpdateModel() + { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL1_XML.getBytes()); + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + CompiledModel previousVersion = dictionaryDAO.getCompiledModel(modelName); + + byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL1_UPDATE1_XML.getBytes()); + model = M2Model.createModel(byteArrayInputStream); + modelName = dictionaryDAO.putModel(model); + CompiledModel newVersion = dictionaryDAO.getCompiledModel(modelName); + + List modelDiffs = dictionaryDAO.diffModel(previousVersion, newVersion); + + for (M2ModelDiff M2ModelDiff : modelDiffs) + { + System.out.println(M2ModelDiff.toString()); + } + + assertEquals(16, modelDiffs.size()); + + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_CREATED)); + assertEquals(2, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(0, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_UPDATED)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_DELETED)); + + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_CREATED)); + assertEquals(2, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(0, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_UPDATED)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_DELETED)); + + assertEquals(0, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_CREATED)); + assertEquals(6, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UPDATED)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_DELETED)); + } + + public void testIncUpdatePropertiesAdded() + { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL2_XML.getBytes()); + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + CompiledModel previousVersion = dictionaryDAO.getCompiledModel(modelName); + + byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL2_EXTRA_PROPERTIES_XML.getBytes()); + model = M2Model.createModel(byteArrayInputStream); + modelName = dictionaryDAO.putModel(model); + CompiledModel newVersion = dictionaryDAO.getCompiledModel(modelName); + + List modelDiffs = dictionaryDAO.diffModel(previousVersion, newVersion); + + for (M2ModelDiff modelDiff : modelDiffs) + { + System.out.println(modelDiff.toString()); + } + + assertEquals(8, modelDiffs.size()); + + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(4, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(2, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_CREATED)); + } + + public void testIncUpdateTypesAndAspectsAdded() + { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL3_XML.getBytes()); + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + CompiledModel previousVersion = dictionaryDAO.getCompiledModel(modelName); + + byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL3_EXTRA_TYPES_AND_ASPECTS_XML.getBytes()); + model = M2Model.createModel(byteArrayInputStream); + modelName = dictionaryDAO.putModel(model); + CompiledModel newVersion = dictionaryDAO.getCompiledModel(modelName); + + List modelDiffs = dictionaryDAO.diffModel(previousVersion, newVersion); + + for (M2ModelDiff modelDiff : modelDiffs) + { + System.out.println(modelDiff.toString()); + } + + assertEquals(8, modelDiffs.size()); + + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_UNCHANGED)); + + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_CREATED)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_CREATED)); + + assertEquals(4, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UNCHANGED)); + } + + public void testIncUpdateAssociationsAdded() + { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL5_XML.getBytes()); + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + CompiledModel previousVersion = dictionaryDAO.getCompiledModel(modelName); + + byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL5_EXTRA_ASSOCIATIONS_XML.getBytes()); + model = M2Model.createModel(byteArrayInputStream); + modelName = dictionaryDAO.putModel(model); + CompiledModel newVersion = dictionaryDAO.getCompiledModel(modelName); + + List modelDiffs = dictionaryDAO.diffModel(previousVersion, newVersion); + + for (M2ModelDiff modelDiff : modelDiffs) + { + System.out.println(modelDiff.toString()); + } + + assertEquals(12, modelDiffs.size()); + + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_UPDATED_INC)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_UNCHANGED)); + + assertEquals(2, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_UNCHANGED)); + + assertEquals(6, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UNCHANGED)); + + assertEquals(2, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_CREATED)); + } + + public void testIncUpdateTitleDescription() + { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL6_XML.getBytes()); + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + CompiledModel previousVersion = dictionaryDAO.getCompiledModel(modelName); + + byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL6_UPDATE1_XML.getBytes()); + model = M2Model.createModel(byteArrayInputStream); + modelName = dictionaryDAO.putModel(model); + CompiledModel newVersion = dictionaryDAO.getCompiledModel(modelName); + + List modelDiffs = dictionaryDAO.diffModel(previousVersion, newVersion); + + for (M2ModelDiff modelDiff : modelDiffs) + { + System.out.println(modelDiff.toString()); + } + + assertEquals(4, modelDiffs.size()); + + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_UPDATED_INC)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(2, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UPDATED_INC)); + } + + public void testNonIncUpdatePropertiesRemoved() + { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL2_EXTRA_PROPERTIES_XML.getBytes()); + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + CompiledModel previousVersion = dictionaryDAO.getCompiledModel(modelName); + + byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL2_XML.getBytes()); + model = M2Model.createModel(byteArrayInputStream); + modelName = dictionaryDAO.putModel(model); + CompiledModel newVersion = dictionaryDAO.getCompiledModel(modelName); + + List modelDiffs = dictionaryDAO.diffModel(previousVersion, newVersion); + + for (M2ModelDiff modelDiff : modelDiffs) + { + System.out.println(modelDiff.toString()); + } + + assertEquals(8, modelDiffs.size()); + + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(4, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(2, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_DELETED)); + } + + public void testNonIncUpdateTypesAndAspectsRemoved() + { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL3_EXTRA_TYPES_AND_ASPECTS_XML.getBytes()); + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + CompiledModel previousVersion = dictionaryDAO.getCompiledModel(modelName); + + byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL3_XML.getBytes()); + model = M2Model.createModel(byteArrayInputStream); + modelName = dictionaryDAO.putModel(model); + CompiledModel newVersion = dictionaryDAO.getCompiledModel(modelName); + + List modelDiffs = dictionaryDAO.diffModel(previousVersion, newVersion); + + for (M2ModelDiff modelDiff : modelDiffs) + { + System.out.println(modelDiff.toString()); + } + + assertEquals(8, modelDiffs.size()); + + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_UNCHANGED)); + + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_DELETED)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_DELETED)); + + assertEquals(4, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UNCHANGED)); + } + + public void testNonIncUpdateDefaultAspectAdded() + { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL4_XML.getBytes()); + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + CompiledModel previousVersion = dictionaryDAO.getCompiledModel(modelName); + + byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL4_EXTRA_DEFAULT_ASPECT_XML.getBytes()); + model = M2Model.createModel(byteArrayInputStream); + modelName = dictionaryDAO.putModel(model); + CompiledModel newVersion = dictionaryDAO.getCompiledModel(modelName); + + List modelDiffs = dictionaryDAO.diffModel(previousVersion, newVersion); + + for (M2ModelDiff modelDiff : modelDiffs) + { + System.out.println(modelDiff.toString()); + } + + assertEquals(4, modelDiffs.size()); + + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_UPDATED)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(2, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UNCHANGED)); + } + + public void testNonIncUpdateAssociationsRemoved() + { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL5_EXTRA_ASSOCIATIONS_XML.getBytes()); + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + CompiledModel previousVersion = dictionaryDAO.getCompiledModel(modelName); + + byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL5_XML.getBytes()); + model = M2Model.createModel(byteArrayInputStream); + modelName = dictionaryDAO.putModel(model); + CompiledModel newVersion = dictionaryDAO.getCompiledModel(modelName); + + List modelDiffs = dictionaryDAO.diffModel(previousVersion, newVersion); + + for (M2ModelDiff modelDiff : modelDiffs) + { + System.out.println(modelDiff.toString()); + } + + assertEquals(12, modelDiffs.size()); + + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_UPDATED)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_TYPE, M2ModelDiff.DIFF_UNCHANGED)); + + assertEquals(2, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_UNCHANGED)); + + assertEquals(6, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_UNCHANGED)); + + assertEquals(2, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASSOCIATION, M2ModelDiff.DIFF_DELETED)); + } + + public void testIncUpdatePropertiesAddedToMandatoryAspect() + { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL7_XML.getBytes()); + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + CompiledModel previousVersion = dictionaryDAO.getCompiledModel(modelName); + + byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL7_EXTRA_PROPERTIES_MANDATORY_ASPECTS_XML.getBytes()); + model = M2Model.createModel(byteArrayInputStream); + modelName = dictionaryDAO.putModel(model); + CompiledModel newVersion = dictionaryDAO.getCompiledModel(modelName); + + List modelDiffs = dictionaryDAO.diffModel(previousVersion, newVersion); + + for (M2ModelDiff modelDiff : modelDiffs) + { + System.out.println(modelDiff.toString()); + } + + assertEquals(3, modelDiffs.size()); + + assertEquals(2, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_CREATED)); + } + + public void testNonIncUpdatePropertiesRemovedFromMandatoryAspect() + { + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL7_EXTRA_PROPERTIES_MANDATORY_ASPECTS_XML.getBytes()); + M2Model model = M2Model.createModel(byteArrayInputStream); + QName modelName = dictionaryDAO.putModel(model); + CompiledModel previousVersion = dictionaryDAO.getCompiledModel(modelName); + + byteArrayInputStream = new ByteArrayInputStream(AbstractModelTest.MODEL7_XML.getBytes()); + model = M2Model.createModel(byteArrayInputStream); + modelName = dictionaryDAO.putModel(model); + CompiledModel newVersion = dictionaryDAO.getCompiledModel(modelName); + + List modelDiffs = dictionaryDAO.diffModel(previousVersion, newVersion); + + for (M2ModelDiff modelDiff : modelDiffs) + { + System.out.println(modelDiff.toString()); + } + + assertEquals(3, modelDiffs.size()); + + assertEquals(2, countDiffs(modelDiffs, M2ModelDiff.TYPE_ASPECT, M2ModelDiff.DIFF_UNCHANGED)); + assertEquals(1, countDiffs(modelDiffs, M2ModelDiff.TYPE_PROPERTY, M2ModelDiff.DIFF_DELETED)); + } + + private int countDiffs(List M2ModelDiffs, String elementType, String diffType) + { + int count = 0; + for (M2ModelDiff modelDiff : M2ModelDiffs) + { + if (modelDiff.getDiffType().equals(diffType) && modelDiff.getElementType().equals(elementType)) + { + count++; + } + } + return count; + } + +} + diff --git a/data-model/src/test/java/org/alfresco/repo/dictionary/constraint/ConstraintsTest.java b/data-model/src/test/java/org/alfresco/repo/dictionary/constraint/ConstraintsTest.java new file mode 100644 index 0000000000..e1528d428e --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/dictionary/constraint/ConstraintsTest.java @@ -0,0 +1,363 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.dictionary.constraint; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import junit.framework.TestCase; + +import org.alfresco.repo.dictionary.DictionaryDAOTest; +import org.alfresco.service.cmr.dictionary.Constraint; +import org.alfresco.service.cmr.dictionary.ConstraintException; +import org.alfresco.service.cmr.dictionary.DictionaryException; +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * This file must be saved using UTF-8. + * + * @see org.alfresco.service.cmr.dictionary.Constraint + * @see org.alfresco.repo.dictionary.constraint.AbstractConstraint + * @see org.alfresco.repo.dictionary.constraint.RegexConstraint + * @see org.alfresco.repo.dictionary.constraint.ListOfValuesConstraint + * + * @author Derek Hulley + */ +public class ConstraintsTest extends TestCase +{ + @Override + protected void setUp() throws Exception + { + // register resource bundles for messages + I18NUtil.registerResourceBundle(DictionaryDAOTest.TEST_RESOURCE_MESSAGES); + } + + /** + * ensure that the default handling of checks on collections will work + */ + public void testCollections() throws Exception + { + DummyConstraint constraint = new DummyConstraint(); + constraint.initialize(); + + assertEquals("DummyConstraint type should be 'org.alfresco.repo.dictionary.constraint.ConstraintsTest$DummyConstraint'", + "org.alfresco.repo.dictionary.constraint.ConstraintsTest$DummyConstraint", + constraint.getType()); + assertNotNull("DummyConstraint should not have empty parameters", constraint.getParameters()); + assertEquals("DummyConstraint should not have empty parameters", 0, constraint.getParameters().size()); + + List dummyObjects = new ArrayList(3); + dummyObjects.add("ABC"); // correct + dummyObjects.add("DEF"); // correct + dummyObjects.add(this); // NO + try + { + constraint.evaluate(dummyObjects); + fail("Failed to detected constraint violation in collection"); + } + catch (ConstraintException e) + { + // expected + checkI18NofExceptionMessage(e); + } + // check that the two strings were properly dealt with + assertEquals("String values not checked", 2, constraint.tested.size()); + } + + public void testNull() throws Exception + { + DummyConstraint constraint = new DummyConstraint(); + constraint.initialize(); + + // a null always passes + constraint.evaluate(null); + } + + private void checkI18NofExceptionMessage(Throwable e) + { + String msg = e.getMessage(); + assertFalse("I18N of constraint message failed", msg.startsWith("d_dictionary.constraint")); + } + + private void evaluate(Constraint constraint, Object value, boolean expectFailure) throws Exception + { + try + { + constraint.evaluate(value); + if (expectFailure) + { + // it should have failed + fail("Failure did not occur: \n" + + " constraint: " + constraint + "\n" + + " value: " + value); + } + } + catch (ConstraintException e) + { + // check if we expect an error + if (expectFailure) + { + // expected - check message I18N + checkI18NofExceptionMessage(e); + } + else + { + // didn't expect it + throw e; + } + } + } + + public void testStringLengthConstraint() throws Exception + { + StringLengthConstraint constraint = new StringLengthConstraint(); + try + { + constraint.setMinLength(-1); + } + catch (DictionaryException e) + { + // expected + checkI18NofExceptionMessage(e); + } + try + { + constraint.setMaxLength(-1); + } + catch (DictionaryException e) + { + // expected + checkI18NofExceptionMessage(e); + } + constraint.setMinLength(3); + constraint.setMaxLength(6); + + assertEquals("StringLengthConstraint type should be 'LENGTH'", + "LENGTH", constraint.getType()); + assertNotNull("StringLengthConstraint should have parameters", constraint.getParameters()); + assertEquals("StringLengthConstraint should have 2 parameters", 2, constraint.getParameters().size()); + assertEquals("minLength should be 3", 3, + constraint.getParameters().get("minLength")); + assertEquals("maxLength should be 6", 6, + constraint.getParameters().get("maxLength")); + + evaluate(constraint, "abc", false); + evaluate(constraint, "abcdef", false); + evaluate(constraint, Arrays.asList("abc", "abcdef"), false); + evaluate(constraint, "ab", true); + evaluate(constraint, "abcdefg", true); + evaluate(constraint, Arrays.asList("abc", "abcdefg"), true); + } + + @SuppressWarnings("unchecked") + public void testListOfValuesConstraint() throws Exception + { + ListOfValuesConstraint constraint = new ListOfValuesConstraint(); + try + { + constraint.setAllowedValues(Collections.emptyList()); + } + catch (DictionaryException e) + { + // expected + checkI18NofExceptionMessage(e); + } + List allowedValues = Arrays.asList(new String[] {"abc", "def", "ghi", " jkl "}); + constraint.setAllowedValues(allowedValues); + + assertEquals("ListOfValuesConstraint type should be 'LIST'", + "LIST", constraint.getType()); + assertNotNull("ListOfValuesConstraint should have parameters", constraint.getParameters()); + assertEquals("ListOfValuesConstraint should have 3 parameters", 3, constraint.getParameters().size()); + assertEquals("caseSensitive should be true", Boolean.TRUE, + constraint.getParameters().get("caseSensitive")); + List allowedValuesParam = (List)constraint.getParameters().get("allowedValues"); + assertEquals("Should be 4 allowable values", 4, allowedValuesParam.size()); + assertEquals("First allowable value should be 'abc'", "abc", allowedValuesParam.get(0)); + assertEquals("First allowable value should be 'def'", "def", allowedValuesParam.get(1)); + assertEquals("First allowable value should be 'ghi'", "ghi", allowedValuesParam.get(2)); + assertEquals("First allowable value should be ' jkl '", " jkl ", allowedValuesParam.get(3)); + Boolean sorted = (Boolean)constraint.getParameters().get("sorted"); + assertFalse("sorting should be false", sorted.booleanValue()); + + evaluate(constraint, "def", false); + evaluate(constraint, "DEF", true); + evaluate(constraint, Arrays.asList("abc", "def"), false); + evaluate(constraint, Arrays.asList("abc", "DEF"), true); + + // now make it case-insensitive + constraint.setCaseSensitive(false); + assertEquals("caseSensitive should be false", Boolean.FALSE, + constraint.getParameters().get("caseSensitive")); + evaluate(constraint, "DEF", false); + evaluate(constraint, Arrays.asList("abc", "DEF"), false); + + // Check leading and trailing spaces are respected + evaluate(constraint, " jkl ", false); + evaluate(constraint, "jkl", true); + evaluate(constraint, " jkl", true); + evaluate(constraint, "jkl ", true); + evaluate(constraint, " jkl ", true); + evaluate(constraint, Arrays.asList(" jkl ", " JKL "), false); + evaluate(constraint, Arrays.asList(" jkl ", " JKL "), true); + } + + public void testNumericRangeConstraint() throws Exception + { + NumericRangeConstraint constraint = new NumericRangeConstraint(); + constraint.initialize(); + + assertEquals("NumericRangeConstraint type should be 'MINMAX'", + "MINMAX", constraint.getType()); + assertNotNull("NumericRangeConstraint should have parameters", constraint.getParameters()); + assertEquals("NumericRangeConstraint should have 2 parameters", 2, constraint.getParameters().size()); + + // check that Double.MIN_VALUE and Double.MAX_VALUE are allowed by default + constraint.evaluate(Double.MIN_VALUE); + constraint.evaluate(Double.MAX_VALUE); + + // check that Double.NaN is not allowed by default + evaluate(constraint, Double.NaN, true); + + // set some limits and check + constraint.setMinValue(-5.0D); + constraint.setMaxValue(+5.0D); + constraint.initialize(); + + assertEquals("minValue should be -5", -5.0D, constraint.getParameters().get("minValue")); + assertEquals("maxValue should be 5", 5.0D, constraint.getParameters().get("maxValue")); + + evaluate(constraint, "-1.0", false); + evaluate(constraint, "+1.0", false); + evaluate(constraint, Arrays.asList(-1, 0, 1), false); + evaluate(constraint, "abc", true); + evaluate(constraint, 56.453E4, true); + evaluate(constraint, Arrays.asList(-1, 6), true); + } + + public void testRegexConstraint() throws Exception + { + RegexConstraint constraint = new RegexConstraint(); + constraint.setExpression("[A-Z]*"); + constraint.setRequiresMatch(true); + constraint.initialize(); + + assertEquals("RegexConstraint type should be 'REGEX'", + "REGEX", constraint.getType()); + assertNotNull("RegexConstraint should have parameters", constraint.getParameters()); + assertEquals("RegexConstraint should have 2 parameters", 2, constraint.getParameters().size()); + assertEquals("requiresMatch should be true", Boolean.TRUE, + constraint.getParameters().get("requiresMatch")); + assertEquals("expression should be [A-Z]*", "[A-Z]*", + constraint.getParameters().get("expression")); + + // do some successful stuff + evaluate(constraint, "ABC", false); + evaluate(constraint, "DEF", false); + + // now some failures + evaluate(constraint, "abc", true); + + // now a case of passing in an object that could be a string + evaluate(constraint, DummyEnum.ABC, false); + evaluate(constraint, DummyEnum.DEF, false); + evaluate(constraint, DummyEnum.abc, true); + + // now switch the requiresMatch around + constraint.setRequiresMatch(false); + constraint.initialize(); + assertEquals("requiresMatch should be false", Boolean.FALSE, + constraint.getParameters().get("requiresMatch")); + + evaluate(constraint, DummyEnum.abc, false); + } + + public void testRegexConstraintFilename() throws Exception + { + // we assume UTF-8 + String expression = new String(".*[\\\"\\*\\\\\\>\\<\\?\\/\\:\\|\\¬\\£\\%\\&\\+\\;]+.*".getBytes("UTF-8")); + String invalidChars = new String("\"*\\>.txt", true); + // ... and a valid one + evaluate(constraint, "Company Home", false); + } + + + private enum DummyEnum + { + ABC, + DEF, + abc; + } + + private class DummyConstraint extends AbstractConstraint + { + private List tested; + + @Override + public void initialize() + { + tested = new ArrayList(4); + } + + /** + * Fails on everything but String values, which pass. + * Null values cause runtime exceptions and all other failures are by + * DictionaryException. + */ + @Override + protected void evaluateSingleValue(Object value) + { + if (value == null) + { + throw new NullPointerException("Null value in dummy test"); + } + else if (value instanceof String) + { + tested.add(value); + } + else + { + throw new ConstraintException("Non-String value"); + } + } + } +} diff --git a/data-model/src/test/java/org/alfresco/repo/index/ShardMethodEnumTest.java b/data-model/src/test/java/org/alfresco/repo/index/ShardMethodEnumTest.java new file mode 100644 index 0000000000..ae7916808d --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/index/ShardMethodEnumTest.java @@ -0,0 +1,95 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.repo.index; + +import org.alfresco.repo.index.shard.ShardMethodEnum; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Unit test to verify enum works as expected + * @author Michael Suzuki + * + */ +public class ShardMethodEnumTest +{ + @Test + public void testTypeACLLegacy() + { + Assert.assertEquals(ShardMethodEnum.MOD_ACL_ID, ShardMethodEnum.getShardMethod("MOD_ACL_ID")); + } + + @Test + public void testDBIDRange() + { + Assert.assertEquals(ShardMethodEnum.DB_ID_RANGE, ShardMethodEnum.getShardMethod("DB_ID_RANGE")); + } + + @Test + public void testTypeACLBasedOnMurmurHash() + { + Assert.assertEquals(ShardMethodEnum.ACL_ID, ShardMethodEnum.getShardMethod("ACL_ID")); + } + @Test + public void testTypeDBID() + { + Assert.assertEquals(ShardMethodEnum.DB_ID, ShardMethodEnum.getShardMethod("DB_ID")); + } + + @Test + public void testTypeEXPLICITID() + { + Assert.assertEquals(ShardMethodEnum.EXPLICIT_ID, ShardMethodEnum.getShardMethod("EXPLICIT_ID")); + } + + @Test + public void testTypeDateTimeStamp() + { + Assert.assertEquals(ShardMethodEnum.DATE, ShardMethodEnum.getShardMethod("DATE")); + } + @Test + public void testTypeProperty() + { + Assert.assertEquals(ShardMethodEnum.PROPERTY, ShardMethodEnum.getShardMethod("PROPERTY")); + } + @Test + public void testUnknown() + { + Assert.assertEquals(ShardMethodEnum.UNKOWN, ShardMethodEnum.getShardMethod("UNKOWN")); + } + @Test + public void testNull() + { + Assert.assertEquals(ShardMethodEnum.UNKOWN, ShardMethodEnum.getShardMethod(null)); + } + @Test + public void testEmpty() + { + Assert.assertEquals(ShardMethodEnum.UNKOWN, ShardMethodEnum.getShardMethod("")); + } +} diff --git a/data-model/src/test/java/org/alfresco/repo/search/impl/parsers/CMISTest.java b/data-model/src/test/java/org/alfresco/repo/search/impl/parsers/CMISTest.java new file mode 100644 index 0000000000..e423b10af2 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/search/impl/parsers/CMISTest.java @@ -0,0 +1,89 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.parsers; + +import java.io.IOException; +import java.io.InputStream; + +import junit.framework.TestCase; + +import org.antlr.gunit.GrammarInfo; +import org.antlr.gunit.gUnitLexer; +import org.antlr.gunit.gUnitParser; +import org.antlr.runtime.ANTLRInputStream; +import org.antlr.runtime.CharStream; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.RecognitionException; + +public class CMISTest extends TestCase +{ + public CMISTest() + { + // TODO Auto-generated constructor stub + } + + public CMISTest(String name) + { + super(name); + // TODO Auto-generated constructor stub + } + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + } + + public void testLexer() throws IOException, RecognitionException + { + ClassLoader cl = CMISTest.class.getClassLoader(); + InputStream modelStream = cl.getResourceAsStream("org/alfresco/repo/search/impl/parsers/cmis_test.gunit"); + + CharStream input = new ANTLRInputStream(modelStream); + + + gUnitExecutor executer = new gUnitExecutor(parse(input), "CMIS"); + + System.out.print(executer.execTest()); // unit test result + + assertEquals("Failures ", 0, executer.failures.size()); + assertEquals("Invalids ", 0, executer.invalids.size()); + } + + private GrammarInfo parse(CharStream input) throws RecognitionException + { + gUnitLexer lexer = new gUnitLexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + + GrammarInfo grammarInfo = new GrammarInfo(); + gUnitParser parser = new gUnitParser(tokens, grammarInfo); + parser.gUnitDef(); // parse gunit script and save elements to grammarInfo + return grammarInfo; + } + + +} diff --git a/data-model/src/test/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSTest.java b/data-model/src/test/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSTest.java new file mode 100644 index 0000000000..249f488eeb --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/search/impl/parsers/CMIS_FTSTest.java @@ -0,0 +1,105 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.parsers; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import junit.framework.TestCase; + +import org.antlr.gunit.GrammarInfo; +import org.antlr.gunit.gUnitLexer; +import org.antlr.gunit.gUnitParser; +import org.antlr.runtime.ANTLRInputStream; +import org.antlr.runtime.CharStream; +import org.antlr.runtime.CommonToken; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.RecognitionException; + +public class CMIS_FTSTest extends TestCase +{ + public CMIS_FTSTest() + { + // TODO Auto-generated constructor stub + } + + public CMIS_FTSTest(String name) + { + super(name); + // TODO Auto-generated constructor stub + } + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + } + + public void testLexer() throws IOException, RecognitionException + { + ClassLoader cl = CMIS_FTSTest.class.getClassLoader(); + InputStream modelStream = cl.getResourceAsStream("org/alfresco/repo/search/impl/parsers/cmis_fts_test.gunit"); + + CharStream input = new ANTLRInputStream(modelStream); + + + gUnitExecutor executer = new gUnitExecutor(parse(input), "FTS"); + + System.out.print(executer.execTest()); // unit test result + + assertEquals("Failures ", 0, executer.failures.size()); + assertEquals("Invalids ", 0, executer.invalids.size()); + } + + public void testLexerOutput() throws IOException + { + String str = "~woof^2"; + CharStream input = new ANTLRInputStream(new ByteArrayInputStream(str.getBytes("UTF-8"))); + FTSLexer lexer = new FTSLexer(input); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + for(CommonToken token : (List)tokenStream.getTokens()) + { + System.out.println(token.toString()); + } + + } + + private GrammarInfo parse(CharStream input) throws RecognitionException + { + gUnitLexer lexer = new gUnitLexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + + GrammarInfo grammarInfo = new GrammarInfo(); + gUnitParser parser = new gUnitParser(tokens, grammarInfo); + parser.gUnitDef(); // parse gunit script and save elements to grammarInfo + return grammarInfo; + } + + +} diff --git a/data-model/src/test/java/org/alfresco/repo/search/impl/parsers/FTSTest.java b/data-model/src/test/java/org/alfresco/repo/search/impl/parsers/FTSTest.java new file mode 100644 index 0000000000..48d1fc6657 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/search/impl/parsers/FTSTest.java @@ -0,0 +1,173 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.search.impl.parsers; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.alfresco.repo.search.impl.querymodel.Column; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.QueryModelFactory; +import org.alfresco.repo.search.impl.querymodel.Selector; +import org.alfresco.repo.search.impl.querymodel.QueryOptions.Connective; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryModelFactory; +import org.alfresco.service.namespace.NamespaceService; +import org.antlr.gunit.GrammarInfo; +import org.antlr.gunit.gUnitLexer; +import org.antlr.gunit.gUnitParser; +import org.antlr.runtime.ANTLRInputStream; +import org.antlr.runtime.ANTLRStringStream; +import org.antlr.runtime.CharStream; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +public class FTSTest extends TestCase +{ + public FTSTest() + { + // TODO Auto-generated constructor stub + } + + public FTSTest(String name) + { + super(name); + // TODO Auto-generated constructor stub + } + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + } + + public void testLexer() throws IOException, RecognitionException + { + ClassLoader cl = FTSTest.class.getClassLoader(); + InputStream modelStream = cl.getResourceAsStream("org/alfresco/repo/search/impl/parsers/fts_test.gunit"); + + CharStream input = new ANTLRInputStream(modelStream); + + gUnitExecutor executer = new gUnitExecutor(parse(input), "FTS"); + + String result = executer.execTest(); + System.out.print(executer.execTest()); // unit test result + + assertEquals("Failures: " + result, 0, executer.failures.size()); + assertEquals("Invalids " + result, 0, executer.invalids.size()); + } + + private GrammarInfo parse(CharStream input) throws RecognitionException + { + gUnitLexer lexer = new gUnitLexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + + GrammarInfo grammarInfo = new GrammarInfo(); + gUnitParser parser = new gUnitParser(tokens, grammarInfo); + parser.gUnitDef(); // parse gunit script and save elements to grammarInfo + return grammarInfo; + } + + public void testMapLoneStar() throws Exception + { + final String ftsExpression = "* AND * AND * AND * AND * AND * AND * AND * AND * AND * AND *"; + AlfrescoFunctionEvaluationContext functionContext = new AlfrescoFunctionEvaluationContext(null, null, NamespaceService.CONTENT_MODEL_1_0_URI); + + Map templates = new HashMap(); + String keywordsTemplate = "%(cm:name cm:title cm:description ia:whatEvent ia:descriptionEvent lnk:title lnk:description TEXT TAG)"; + String keywordsKey = "keywords"; + templates.put(keywordsKey, keywordsTemplate); + + final FTSParser.Mode mode = FTSParser.Mode.DEFAULT_DISJUNCTION; + final Connective defaultFieldConnective = Connective.OR; + + class TestMock extends FTSQueryParser.TestNodeBuilder + { + private void test(CommonTree initialNode, CommonTree replacedNode) + { + if (initialNode.getType() == FTSParser.TERM && + initialNode.getChildCount() == 1 && + initialNode.getChild(0).getType() == FTSParser.STAR) + { + // input is the lone star + Tree node = replacedNode; + while (true) + { + if (node.getChildCount() == 1) + { + node = node.getChild(0); + if (node.getType() == FTSParser.TERM) + { + assertEquals("Lone star should be mapped to " + FTSQueryParser.VALUE_REPLACELONESTAR, node.getChildCount(), 2); + Tree child1 = node.getChild(0); + assertEquals("Lone star should be mapped to " + FTSQueryParser.VALUE_REPLACELONESTAR, child1.getType(), FTSParser.ID); + assertEquals("Lone star should be mapped to " + FTSQueryParser.VALUE_REPLACELONESTAR, child1.getText(), "T"); + Tree child2 = node.getChild(1); + assertEquals("Lone star should be mapped to " + FTSQueryParser.VALUE_REPLACELONESTAR, child2.getType(), FTSParser.FIELD_REF); + assertEquals("Lone star should be mapped to " + FTSQueryParser.VALUE_REPLACELONESTAR, child2.getChild(0).getText(), "ISNODE"); + // checking done + break; + } + } + else + { + // wrong structure of the replaced node + fail("Lone star should be mapped to " + FTSQueryParser.VALUE_REPLACELONESTAR); + } + } + } + } + + @Override + protected CommonTree build(CommonTree fieldReferenceNode, CommonTree argNode, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, + Selector selector, Map columnMap, Map templateTrees, String defaultField) + { + CommonTree testNode = super.build(fieldReferenceNode, argNode, factory, functionEvaluationContext, selector, columnMap, templateTrees, defaultField); + test(argNode, testNode); + return testNode; + } + } + + FTSQueryParser.setTestNodeBuilder(new TestMock()); + try + { + FTSQueryParser.buildFTS(ftsExpression, new LuceneQueryModelFactory(), functionContext, null, null, + mode, defaultFieldConnective, templates, keywordsKey, FTSQueryParser.RerankPhase.SINGLE_PASS); + } + finally + { + // set default logic + FTSQueryParser.setTestNodeBuilder(new FTSQueryParser.TestNodeBuilder()); + } + } + +} diff --git a/data-model/src/test/java/org/alfresco/repo/search/impl/parsers/gUnitExecutor.java b/data-model/src/test/java/org/alfresco/repo/search/impl/parsers/gUnitExecutor.java new file mode 100644 index 0000000000..75ff2b38b8 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/search/impl/parsers/gUnitExecutor.java @@ -0,0 +1,341 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +/* + [The "BSD licence"] + Copyright (c) 2007-2008 Leon Jen-Yuan Su + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.alfresco.repo.search.impl.parsers; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; + +import org.antlr.gunit.GrammarInfo; +import org.antlr.gunit.gUnitTestInput; +import org.antlr.gunit.gUnitTestResult; +import org.antlr.runtime.ANTLRFileStream; +import org.antlr.runtime.ANTLRStringStream; +import org.antlr.runtime.CharStream; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.Lexer; +import org.antlr.runtime.Token; +import org.antlr.runtime.TokenStream; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.TreeAdaptor; +import org.antlr.stringtemplate.StringTemplate; + +public class gUnitExecutor extends org.antlr.gunit.gUnitExecutor +{ + private String testsuiteDir; + + private PrintStream console = System.out; + + private PrintStream consoleErr = System.err; + + public gUnitExecutor(GrammarInfo grammarInfo, String testsuiteDir) + { + super(grammarInfo, testsuiteDir); + this.testsuiteDir = testsuiteDir; + } + + // TODO: throw proper exceptions + protected gUnitTestResult runParser(String parserName, String lexerName, String testRuleName, gUnitTestInput testInput) throws Exception + { + CharStream input; + Class lexer = null; + Class parser = null; + PrintStream ps = null; // for redirecting stdout later + PrintStream ps2 = null; // for redirecting stderr later + try + { + /** Set up ANTLR input stream based on input source, file or String */ + input = getANTLRInputStream(testInput); + + /** Use Reflection to create instances of lexer and parser */ + lexer = classForName(lexerName); + Class[] lexArgTypes = new Class[] { CharStream.class }; // assign type to lexer's args + Constructor lexConstructor = lexer.getConstructor(lexArgTypes); + Object[] lexArgs = new Object[] { input }; // assign value to lexer's args + Object lexObj = lexConstructor.newInstance(lexArgs); // makes new instance of lexer + + CommonTokenStream tokens = new CommonTokenStream((Lexer) lexObj); + + parser = classForName(parserName); + Class[] parArgTypes = new Class[] { TokenStream.class }; // assign type to parser's args + Constructor parConstructor = parser.getConstructor(parArgTypes); + Object[] parArgs = new Object[] { tokens }; // assign value to parser's args + Object parObj = parConstructor.newInstance(parArgs); // makes new instance of parser + + // set up customized tree adaptor if necessary + if (grammarInfo.getAdaptor() != null) + { + parArgTypes = new Class[] { TreeAdaptor.class }; + Method _setTreeAdaptor = parser.getMethod("setTreeAdaptor", parArgTypes); + Class _treeAdaptor = classForName(grammarInfo.getAdaptor()); + _setTreeAdaptor.invoke(parObj, _treeAdaptor.newInstance()); + } + + Method ruleName = parser.getMethod(testRuleName); + + /** Start of I/O Redirecting */ + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayOutputStream err = new ByteArrayOutputStream(); + ps = new PrintStream(out); + ps2 = new PrintStream(err); + System.setOut(ps); + System.setErr(ps2); + /** End of redirecting */ + + /** Invoke grammar rule, and store if there is a return value */ + Object ruleReturn = ruleName.invoke(parObj); + String astString = null; + String stString = null; + /** If rule has return value, determine if it contains an AST or a ST */ + if (ruleReturn != null) + { + if (ruleReturn.getClass().toString().indexOf(testRuleName + "_return") > 0) + { + try + { // NullPointerException may happen here... + Class _return = classForName(parserName + "$" + testRuleName + "_return"); + Method[] methods = _return.getDeclaredMethods(); + for (Method method : methods) + { + if (method.getName().equals("getTree")) + { + Method returnName = _return.getMethod("getTree"); + CommonTree tree = (CommonTree) returnName.invoke(ruleReturn); + astString = tree.toStringTree(); + } + else if (method.getName().equals("getTemplate")) + { + Method returnName = _return.getMethod("getTemplate"); + StringTemplate st = (StringTemplate) returnName.invoke(ruleReturn); + stString = st.toString(); + } + } + } + catch (Exception e) + { + System.err.println(e); // Note: If any exception occurs, the test is viewed as failed. + } + } + } + + // Count tokens EOF only once .... + int count = 0; + boolean foundEof = false; + for (Token token : (List) tokens.getTokens()) + { + if (!foundEof) + { + if (token.getType() == Token.EOF) + { + foundEof = true; + if(testRuleName.equals("ftsQuery") || testRuleName.equals("query")) + { + count++; + } + } + else + { + count++; + } + + } + } + + /** Invalid input */ + if (tokens.index() != count) + { + // throw new InvalidInputException(); + ps2.print("Invalid input"); + } + + if (err.toString().length() > 0) + { + gUnitTestResult testResult = new gUnitTestResult(false, err.toString()); + testResult.setError(err.toString()); + return testResult; + } + String stdout = null; + // TODO: need to deal with the case which has both ST return value and stdout + if (out.toString().length() > 0) + { + stdout = out.toString(); + } + if (astString != null) + { // Return toStringTree of AST + return new gUnitTestResult(true, stdout, astString); + } + else if (stString != null) + {// Return toString of ST + return new gUnitTestResult(true, stdout, stString); + } + + if (ruleReturn != null) + { + // TODO: currently only works for a single return with int or String value + return new gUnitTestResult(true, stdout, String.valueOf(ruleReturn)); + } + return new gUnitTestResult(true, stdout, stdout); + } + catch (IOException e) + { + return getTestExceptionResult(e); + } + catch (ClassNotFoundException e) + { + e.printStackTrace(); + System.exit(1); + } + catch (SecurityException e) + { + e.printStackTrace(); + System.exit(1); + } + catch (NoSuchMethodException e) + { + e.printStackTrace(); + System.exit(1); + } + catch (IllegalArgumentException e) + { + e.printStackTrace(); + System.exit(1); + } + catch (InstantiationException e) + { + e.printStackTrace(); + System.exit(1); + } + catch (IllegalAccessException e) + { + e.printStackTrace(); + System.exit(1); + } + catch (InvocationTargetException e) + { // This exception could be caused from ANTLR Runtime Exception, e.g. MismatchedTokenException + return getTestExceptionResult(e); + } + finally + { + try + { + if (ps != null) + ps.close(); + if (ps2 != null) + ps2.close(); + System.setOut(console); // Reset standard output + System.setErr(consoleErr); // Reset standard err out + } + catch (Exception e) + { + e.printStackTrace(); + } + } + // TODO: verify this: + throw new Exception("This should be unreachable?"); + } + + // Create ANTLR input stream based on input source, file or String + private CharStream getANTLRInputStream(gUnitTestInput testInput) throws IOException + { + CharStream input; + if (testInput.isFile) + { + String filePath = testInput.input; + File testInputFile = new File(filePath); + // if input test file is not found under the current dir, try to look for it from dir where the testsuite + // file locates + if (!testInputFile.exists()) + { + testInputFile = new File(this.testsuiteDir, filePath); + if (testInputFile.exists()) + filePath = testInputFile.getCanonicalPath(); + // if still not found, also try to look for it under the package dir + else if (grammarInfo.getGrammarPackage() != null) + { + testInputFile = new File("." + File.separator + grammarInfo.getGrammarPackage().replace(".", File.separator), filePath); + if (testInputFile.exists()) + filePath = testInputFile.getCanonicalPath(); + } + } + input = new ANTLRFileStream(filePath); + } + else + { + input = new ANTLRStringStream(testInput.input); + } + return input; + } + + // set up the cause of exception or the exception name into a gUnitTestResult instance + private gUnitTestResult getTestExceptionResult(Exception e) + { + gUnitTestResult testResult; + if (e.getCause() != null) + { + testResult = new gUnitTestResult(false, e.getCause().toString(), true); + testResult.setError(e.getCause().toString()); + } + else + { + testResult = new gUnitTestResult(false, e.toString(), true); + testResult.setError(e.toString()); + } + return testResult; + } + +} diff --git a/data-model/src/test/java/org/alfresco/repo/security/authentication/InMemoryTicketComponentTest.java b/data-model/src/test/java/org/alfresco/repo/security/authentication/InMemoryTicketComponentTest.java new file mode 100644 index 0000000000..f37f73dced --- /dev/null +++ b/data-model/src/test/java/org/alfresco/repo/security/authentication/InMemoryTicketComponentTest.java @@ -0,0 +1,87 @@ +package org.alfresco.repo.security.authentication; + +import org.alfresco.service.cmr.repository.datatype.Duration; +import org.junit.Test; + +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.fail; + +/** + * This test class is not exhaustive. + * Please add here tests that are relevant for the + * org.alfresco.repo.security.authentication.InMemoryTicketComponentImpl and + * org.alfresco.repo.security.authentication.InMemoryTicketComponentImpl.Ticket classes + */ +public class InMemoryTicketComponentTest +{ + @Test + public void testTicketCollectionReadinessDoNotExpire() + { + final Duration validDuration = new Duration("PT1H"); + final InMemoryTicketComponentImpl.ExpiryMode expireMode = InMemoryTicketComponentImpl.ExpiryMode.DO_NOT_EXPIRE; + final String randomUserName = "someUserName"; + + final Date someDate = null; + + checkEqualsAndHashCode(validDuration, expireMode, someDate, randomUserName); + } + + @Test + public void testTicketCollectionReadinessAfterInactivity() + { + final Duration validDuration = new Duration("PT1H"); + final InMemoryTicketComponentImpl.ExpiryMode expireMode = InMemoryTicketComponentImpl.ExpiryMode.AFTER_INACTIVITY; + final String randomUserName = "someUserName"; + + final Date someDate = new Date(); + + checkEqualsAndHashCode(validDuration, expireMode, someDate, randomUserName); + + checkInvalidExpireDateParameter(validDuration, expireMode, randomUserName); + } + + @Test + public void testTicketCollectionReadinessAfterFixTime() + { + final Duration validDuration = new Duration("PT1H"); + final InMemoryTicketComponentImpl.ExpiryMode expireMode = InMemoryTicketComponentImpl.ExpiryMode.AFTER_FIXED_TIME; + final String randomUserName = "someUserName"; + + final Date someDate = new Date(); + + checkEqualsAndHashCode(validDuration, expireMode, someDate, randomUserName); + + checkInvalidExpireDateParameter(validDuration, expireMode, randomUserName); + } + + private void checkEqualsAndHashCode(Duration validDuration, InMemoryTicketComponentImpl.ExpiryMode expireMode, Date someDate, + String randomUserName) + { + InMemoryTicketComponentImpl.Ticket ticket1 = new InMemoryTicketComponentImpl.Ticket(expireMode, someDate, randomUserName, validDuration); + InMemoryTicketComponentImpl.Ticket ticket2 = new InMemoryTicketComponentImpl.Ticket(expireMode, someDate, randomUserName, validDuration); + ticket1.equals(ticket2); + + final Set aSet = new HashSet<>(); + for (int i = 0; i < 100000; ++i) + { + InMemoryTicketComponentImpl.Ticket ticket = new InMemoryTicketComponentImpl.Ticket(expireMode, someDate, randomUserName, validDuration); + aSet.add(ticket); + } + } + + private void checkInvalidExpireDateParameter(Duration validDuration, InMemoryTicketComponentImpl.ExpiryMode expireMode, String randomUserName) + { + try + { + checkEqualsAndHashCode(validDuration, expireMode, null, randomUserName); + fail("expire date should not be allowed as null in this expireMode case"); + } + catch (IllegalArgumentException e) + { + //we expect this, we sent the date to be null + } + } +} diff --git a/data-model/src/test/java/org/alfresco/service/cmr/repository/MLTextTest.java b/data-model/src/test/java/org/alfresco/service/cmr/repository/MLTextTest.java new file mode 100644 index 0000000000..d839848e86 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/service/cmr/repository/MLTextTest.java @@ -0,0 +1,60 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.util.Locale; + +import junit.framework.TestCase; + +/** + * @see org.alfresco.service.cmr.repository.MLText + * + * @author Derek Hulley + */ +public class MLTextTest extends TestCase +{ + MLText mlText; + + @Override + protected void setUp() + { + mlText = new MLText(Locale.CANADA_FRENCH, Locale.CANADA_FRENCH.toString()); + mlText.addValue(Locale.US, Locale.US.toString()); + mlText.addValue(Locale.UK, Locale.UK.toString()); + mlText.addValue(Locale.FRENCH, Locale.FRENCH.toString()); + mlText.addValue(Locale.CHINESE, Locale.CHINESE.toString()); + } + + public void testGetByLocale() + { + // check each value + assertNull("Expected nothing for German", mlText.getValue(Locale.GERMAN)); + assertEquals(Locale.US.toString(), mlText.get(Locale.US)); + assertEquals(Locale.UK.toString(), mlText.get(Locale.UK)); + assertNull("Expected no value for Japanese", mlText.getValue(Locale.JAPANESE)); + assertNotNull("Expected an arbirary value for Japanese", mlText.getClosestValue(Locale.JAPANESE)); + } +} diff --git a/data-model/src/test/java/org/alfresco/service/cmr/repository/NodeRefTest.java b/data-model/src/test/java/org/alfresco/service/cmr/repository/NodeRefTest.java new file mode 100644 index 0000000000..223a65a8f1 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/service/cmr/repository/NodeRefTest.java @@ -0,0 +1,71 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import junit.framework.TestCase; + +/** + * @see org.alfresco.service.cmr.repository.NodeRef + * + * @author Derek Hulley + */ +public class NodeRefTest extends TestCase +{ + + public NodeRefTest(String name) + { + super(name); + } + + public void testStoreRef() throws Exception + { + StoreRef storeRef = new StoreRef("ABC", "123"); + assertEquals("toString failure", "ABC://123", storeRef.toString()); + + StoreRef storeRef2 = new StoreRef(storeRef.getProtocol(), storeRef + .getIdentifier()); + assertEquals("equals failure", storeRef, storeRef2); + } + + public void testNodeRef() throws Exception + { + StoreRef storeRef = new StoreRef("ABC", "123"); + NodeRef nodeRef = new NodeRef(storeRef, "456"); + assertEquals("toString failure", "ABC://123/456", nodeRef.toString()); + + NodeRef nodeRef2 = new NodeRef(storeRef, "456"); + assertEquals("equals failure", nodeRef, nodeRef2); + } + + public void testNodeRefPattern() throws Exception + { + StoreRef storeRef = new StoreRef("ABC", "123"); + NodeRef nodeRef = new NodeRef(storeRef, "456"); + + assertTrue(NodeRef.isNodeRef(nodeRef.toString())); + assertFalse(NodeRef.isNodeRef("sdfsdf:sdfsdf")); + } +} diff --git a/data-model/src/test/java/org/alfresco/service/cmr/repository/PathTest.java b/data-model/src/test/java/org/alfresco/service/cmr/repository/PathTest.java new file mode 100644 index 0000000000..2ff901b10e --- /dev/null +++ b/data-model/src/test/java/org/alfresco/service/cmr/repository/PathTest.java @@ -0,0 +1,120 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import org.alfresco.service.namespace.QName; + +import junit.framework.TestCase; + +/** + * @see org.alfresco.service.cmr.repository.Path + * + * @author Derek Hulley + */ +public class PathTest extends TestCase +{ + private Path absolutePath; + private Path relativePath; + private QName typeQName; + private QName qname; + private StoreRef storeRef; + private NodeRef parentRef; + private NodeRef childRef; + + public PathTest(String name) + { + super(name); + } + + public void setUp() throws Exception + { + super.setUp(); + absolutePath = new Path(); + relativePath = new Path(); + typeQName = QName.createQName("http://www.alfresco.org/PathTest/1.0", "testType"); + qname = QName.createQName("http://www.google.com", "documentx"); + storeRef = new StoreRef("x", "y"); + parentRef = new NodeRef(storeRef, "P"); + childRef = new NodeRef(storeRef, "C"); + } + + public void testQNameElement() throws Exception + { + // plain + Path.Element element = new Path.ChildAssocElement(new ChildAssociationRef(typeQName, parentRef, qname, childRef)); + assertEquals("Element string incorrect", + qname.toString(), + element.getElementString()); + // sibling + element = new Path.ChildAssocElement(new ChildAssociationRef(typeQName, parentRef, qname, childRef, true, 5)); + assertEquals("Element string incorrect", "{http://www.google.com}documentx[5]", element.getElementString()); + } + + public void testElementTypes() throws Exception + { + Path.Element element = new Path.DescendentOrSelfElement(); + assertEquals("DescendentOrSelf element incorrect", + "descendant-or-self::node()", + element.getElementString()); + + element = new Path.ParentElement(); + assertEquals("Parent element incorrect", "..", element.getElementString()); + + element = new Path.SelfElement(); + assertEquals("Self element incorrect", ".", element.getElementString()); + } + + public void testAppendingAndPrepending() throws Exception + { + Path.Element element0 = new Path.ChildAssocElement(new ChildAssociationRef(null, null, null, parentRef)); + Path.Element element1 = new Path.ChildAssocElement(new ChildAssociationRef(typeQName, parentRef, qname, childRef, true, 4)); + Path.Element element2 = new Path.DescendentOrSelfElement(); + Path.Element element3 = new Path.ParentElement(); + Path.Element element4 = new Path.SelfElement(); + // append them all to the path + absolutePath.append(element0).append(element1).append(element2).append(element3).append(element4); + relativePath.append(element1).append(element2).append(element3).append(element4); + // check + assertEquals("Path appending didn't work", + "/{http://www.google.com}documentx[4]/descendant-or-self::node()/../.", + absolutePath.toString()); + + // copy the path + Path copy = new Path(); + copy.append(relativePath).append(relativePath); + // check + assertEquals("Path appending didn't work", + relativePath.toString() + "/" + relativePath.toString(), + copy.toString()); + + // prepend + relativePath.prepend(element2); + // check + assertEquals("Prepending didn't work", + "descendant-or-self::node()/{http://www.google.com}documentx[4]/descendant-or-self::node()/../.", + relativePath.toString()); + } +} \ No newline at end of file diff --git a/data-model/src/test/java/org/alfresco/service/cmr/repository/PeriodTest.java b/data-model/src/test/java/org/alfresco/service/cmr/repository/PeriodTest.java new file mode 100644 index 0000000000..53b72900d2 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/service/cmr/repository/PeriodTest.java @@ -0,0 +1,85 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository; + +import java.text.ParseException; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +/** + * + * @see org.alfresco.service.cmr.repository.Period + * @author Andreea Nechifor + * + */ +public class PeriodTest extends TestCase +{ + + public void testMapToPeriod() throws ParseException + { + Map periodArgs = new HashMap(); + periodArgs.put("periodType", "day"); + Period period = new Period(periodArgs); + assertNotNull(period.getPeriodType()); + assertEquals("day", period.getPeriodType()); + assertNull(period.getExpression()); + + periodArgs.put("expression", "0"); + period = new Period(periodArgs); + assertNotNull(period.getPeriodType()); + assertNotNull(period.getExpression()); + assertEquals("day", period.getPeriodType()); + assertEquals("0", period.getExpression()); + + try + { + periodArgs = null; + period = new Period(periodArgs); + fail("the source map must not be null"); + } + catch (IllegalArgumentException e) + { + // Check the exception is source. + assertTrue(e.getMessage().contains("Cannot create Period.")); + } + + try + { + periodArgs = new HashMap(); + period = new Period(periodArgs); + fail("the periodType must not be null"); + } + catch (IllegalArgumentException e) + { + // Check the exception is periodType. + assertTrue(e.getMessage().contains("Cannot create Period with null periodType")); + } + + } + +} diff --git a/data-model/src/test/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverterTest.java b/data-model/src/test/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverterTest.java new file mode 100644 index 0000000000..9b6af08ff5 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/service/cmr/repository/datatype/DefaultTypeConverterTest.java @@ -0,0 +1,355 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.repository.datatype; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import junit.framework.TestCase; + +import org.alfresco.service.cmr.repository.MLText; +import org.alfresco.service.cmr.repository.Period; +import org.alfresco.util.VersionNumber; +import org.alfresco.util.ISO8601DateFormat; + +public class DefaultTypeConverterTest extends TestCase +{ + + public DefaultTypeConverterTest() + { + super(); + } + + public DefaultTypeConverterTest(String arg0) + { + super(arg0); + } + + public void testPrimitives() + { + assertEquals(Boolean.valueOf(false), DefaultTypeConverter.INSTANCE.convert(Boolean.class, false)); + assertEquals(Boolean.valueOf(true), DefaultTypeConverter.INSTANCE.convert(Boolean.class, true)); + assertEquals(Character.valueOf('a'), DefaultTypeConverter.INSTANCE.convert(Character.class, 'a')); + assertEquals(Byte.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Byte.class, (byte) 3)); + assertEquals(Short.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Short.class, (short) 4)); + assertEquals(Integer.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Integer.class, (int) 5)); + assertEquals(Long.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Long.class, (long) 6)); + assertEquals(Float.valueOf("7.1"), DefaultTypeConverter.INSTANCE.convert(Float.class, (float) 7.1)); + assertEquals(Double.valueOf("123.123"), DefaultTypeConverter.INSTANCE.convert(Double.class, (double) 123.123)); + } + + public void testNoConversion() + { + assertEquals(Boolean.valueOf(false), DefaultTypeConverter.INSTANCE.convert(Boolean.class, Boolean.valueOf(false))); + assertEquals(Boolean.valueOf(true), DefaultTypeConverter.INSTANCE.convert(Boolean.class, Boolean.valueOf(true))); + assertEquals(Character.valueOf('w'), DefaultTypeConverter.INSTANCE.convert(Character.class, Character.valueOf('w'))); + assertEquals(Byte.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Byte.class, Byte.valueOf("3"))); + assertEquals(Short.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Short.class, Short.valueOf("4"))); + assertEquals(Integer.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Integer.class, Integer.valueOf("5"))); + assertEquals(Long.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Long.class, Long.valueOf("6"))); + assertEquals(Float.valueOf("7.1"), DefaultTypeConverter.INSTANCE.convert(Float.class, Float.valueOf("7.1"))); + assertEquals(Double.valueOf("123.123"), DefaultTypeConverter.INSTANCE.convert(Double.class, Double.valueOf("123.123"))); + assertEquals(Double.valueOf("123.123"), DefaultTypeConverter.INSTANCE.convert(Double.class, Double.valueOf("123.123"))); + assertEquals(new BigInteger("1234567890123456789"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, new BigInteger("1234567890123456789"))); + assertEquals(new BigDecimal("12345678901234567890.12345678901234567890"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, new BigDecimal("12345678901234567890.12345678901234567890"))); + Date date = new Date(); + assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, date)); + assertEquals(new Duration("P25D"), DefaultTypeConverter.INSTANCE.convert(Duration.class, new Duration("P25D"))); + assertEquals("woof", DefaultTypeConverter.INSTANCE.convert(String.class, "woof")); + } + + public void testToString() + { + assertEquals("true", DefaultTypeConverter.INSTANCE.convert(String.class, new Boolean(true))); + assertEquals("false", DefaultTypeConverter.INSTANCE.convert(String.class, new Boolean(false))); + assertEquals("v", DefaultTypeConverter.INSTANCE.convert(String.class, Character.valueOf('v'))); + assertEquals("3", DefaultTypeConverter.INSTANCE.convert(String.class, Byte.valueOf("3"))); + assertEquals("4", DefaultTypeConverter.INSTANCE.convert(String.class, Short.valueOf("4"))); + assertEquals("5", DefaultTypeConverter.INSTANCE.convert(String.class, Integer.valueOf("5"))); + assertEquals("6", DefaultTypeConverter.INSTANCE.convert(String.class, Long.valueOf("6"))); + assertEquals("7.1", DefaultTypeConverter.INSTANCE.convert(String.class, Float.valueOf("7.1"))); + assertEquals("NaN", DefaultTypeConverter.INSTANCE.convert(String.class, Float.NaN)); + assertEquals("-Infinity", DefaultTypeConverter.INSTANCE.convert(String.class, Float.NEGATIVE_INFINITY)); + assertEquals("Infinity", DefaultTypeConverter.INSTANCE.convert(String.class, Float.POSITIVE_INFINITY)); + assertEquals("123.123", DefaultTypeConverter.INSTANCE.convert(String.class, Double.valueOf("123.123"))); + assertEquals("NaN", DefaultTypeConverter.INSTANCE.convert(String.class, Double.NaN)); + assertEquals("-Infinity", DefaultTypeConverter.INSTANCE.convert(String.class, Double.NEGATIVE_INFINITY)); + assertEquals("Infinity", DefaultTypeConverter.INSTANCE.convert(String.class, Double.POSITIVE_INFINITY)); + assertEquals("1234567890123456789", DefaultTypeConverter.INSTANCE.convert(String.class, new BigInteger("1234567890123456789"))); + assertEquals("12345678901234567890.12345678901234567890", DefaultTypeConverter.INSTANCE.convert(String.class, new BigDecimal("12345678901234567890.12345678901234567890"))); + Date date = new Date(); + assertEquals(ISO8601DateFormat.format(date), DefaultTypeConverter.INSTANCE.convert(String.class, date)); + assertEquals("P0Y25D", DefaultTypeConverter.INSTANCE.convert(String.class, new Duration("P0Y25D"))); + assertEquals("woof", DefaultTypeConverter.INSTANCE.convert(String.class, "woof")); + // MLText + MLText mlText = new MLText("woof"); + mlText.addValue(Locale.SIMPLIFIED_CHINESE, "缂"); + assertEquals("woof", DefaultTypeConverter.INSTANCE.convert(String.class, mlText)); + // Locale + assertEquals("fr_FR_", DefaultTypeConverter.INSTANCE.convert(String.class, Locale.FRANCE)); + // VersionNumber + assertEquals("1.2.3", DefaultTypeConverter.INSTANCE.convert(String.class, new VersionNumber("1.2.3"))); + // Period + assertEquals("period", DefaultTypeConverter.INSTANCE.convert(String.class, new Period("period"))); + assertEquals("period|12", DefaultTypeConverter.INSTANCE.convert(String.class, new Period("period|12"))); + // Java Class + assertEquals(this.getClass(), DefaultTypeConverter.INSTANCE.convert(Class.class, this.getClass().getName())); + } + + public void testFromString() + { + assertEquals(Boolean.valueOf(true), DefaultTypeConverter.INSTANCE.convert(Boolean.class, "True")); + assertEquals(Boolean.valueOf(false), DefaultTypeConverter.INSTANCE.convert(Boolean.class, "woof")); + assertEquals(Character.valueOf('w'), DefaultTypeConverter.INSTANCE.convert(Character.class, "w")); + assertEquals(Byte.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Byte.class, "3")); + assertEquals(Short.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Short.class, "4")); + assertEquals(Integer.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Integer.class, "5")); + assertEquals(Long.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Long.class, "6")); + assertEquals(Float.valueOf("7.1"), DefaultTypeConverter.INSTANCE.convert(Float.class, "7.1")); + assertEquals(Float.NaN, DefaultTypeConverter.INSTANCE.convert(Float.class, "NaN")); + assertEquals(Float.NEGATIVE_INFINITY, DefaultTypeConverter.INSTANCE.convert(Float.class, "-Infinity")); + assertEquals(Float.POSITIVE_INFINITY, DefaultTypeConverter.INSTANCE.convert(Float.class, "Infinity")); + assertEquals(Double.valueOf("123.123"), DefaultTypeConverter.INSTANCE.convert(Double.class, "123.123")); + assertEquals(Double.NaN, DefaultTypeConverter.INSTANCE.convert(Double.class, "NaN")); + assertEquals(Double.NEGATIVE_INFINITY, DefaultTypeConverter.INSTANCE.convert(Double.class, "-Infinity")); + assertEquals(Double.POSITIVE_INFINITY, DefaultTypeConverter.INSTANCE.convert(Double.class, "Infinity")); + assertEquals(new BigInteger("1234567890123456789"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, "1234567890123456789")); + assertEquals(new BigDecimal("12345678901234567890.12345678901234567890"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, "12345678901234567890.12345678901234567890")); + GregorianCalendar cal = new GregorianCalendar(); + cal.set(Calendar.YEAR, 2004); + cal.set(Calendar.MONTH, 3); + cal.set(Calendar.DAY_OF_MONTH, 12); + cal.set(Calendar.HOUR, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + String isoDate = ISO8601DateFormat.format(cal.getTime()); + assertEquals(isoDate, ISO8601DateFormat.format(DefaultTypeConverter.INSTANCE.convert(Date.class, isoDate))); + assertEquals(new Duration("P25D"), DefaultTypeConverter.INSTANCE.convert(Duration.class, "P25D")); + assertEquals("woof", DefaultTypeConverter.INSTANCE.convert(String.class, "woof")); + + MLText converted = DefaultTypeConverter.INSTANCE.convert(MLText.class, "woof"); + assertEquals("woof", converted.getValue(Locale.getDefault())); + + assertEquals(Locale.FRANCE, DefaultTypeConverter.INSTANCE.convert(Locale.class, "fr_FR")); + assertEquals(Locale.FRANCE, DefaultTypeConverter.INSTANCE.convert(Locale.class, "fr_FR_")); + + assertEquals(new VersionNumber("1.2.3"), DefaultTypeConverter.INSTANCE.convert(VersionNumber.class, "1.2.3")); + assertEquals(new Period("period"), DefaultTypeConverter.INSTANCE.convert(Period.class, "period")); + assertEquals(new Period("period|12"), DefaultTypeConverter.INSTANCE.convert(Period.class, "period|12")); + Map periodMap = new HashMap(); + periodMap.put("periodType","month"); + periodMap.put("expression","1"); + assertEquals(new Period(periodMap), DefaultTypeConverter.INSTANCE.convert(Period.class, periodMap)); + // Java Class + assertEquals(this.getClass().getName(), DefaultTypeConverter.INSTANCE.convert(String.class, this.getClass())); + } + + public void testPrimativeAccessors() + { + assertEquals(false, DefaultTypeConverter.INSTANCE.convert(Boolean.class, false).booleanValue()); + assertEquals(true, DefaultTypeConverter.INSTANCE.convert(Boolean.class, true).booleanValue()); + assertEquals('a', DefaultTypeConverter.INSTANCE.convert(Character.class, 'a').charValue()); + assertEquals((byte) 3, DefaultTypeConverter.INSTANCE.convert(Byte.class, (byte) 3).byteValue()); + assertEquals((short) 4, DefaultTypeConverter.INSTANCE.convert(Short.class, (short) 4).shortValue()); + assertEquals((int) 5, DefaultTypeConverter.INSTANCE.convert(Integer.class, (int) 5).intValue()); + assertEquals((long) 6, DefaultTypeConverter.INSTANCE.convert(Long.class, (long) 6).longValue()); + assertEquals((float) 7.1, DefaultTypeConverter.INSTANCE.convert(Float.class, (float) 7.1).floatValue()); + assertEquals((double) 123.123, DefaultTypeConverter.INSTANCE.convert(Double.class, (double) 123.123).doubleValue()); + } + + public void testInterConversions() + { + assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, Byte.valueOf("1"))); + assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, Byte.valueOf("2"))); + assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, Byte.valueOf("3"))); + assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, Byte.valueOf("4"))); + assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, Byte.valueOf("5"))); + assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, Byte.valueOf("6"))); + assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, Byte.valueOf("7"))); + assertEquals(new BigDecimal("8"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, Byte.valueOf("8"))); + + assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, Short.valueOf("1"))); + assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, Short.valueOf("2"))); + assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, Short.valueOf("3"))); + assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, Short.valueOf("4"))); + assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, Short.valueOf("5"))); + assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, Short.valueOf("6"))); + assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, Short.valueOf("7"))); + assertEquals(new BigDecimal("8"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, Short.valueOf("8"))); + + assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, Integer.valueOf("1"))); + assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, Integer.valueOf("2"))); + assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, Integer.valueOf("3"))); + assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, Integer.valueOf("4"))); + assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, Integer.valueOf("5"))); + assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, Integer.valueOf("6"))); + assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, Integer.valueOf("7"))); + assertEquals(new BigDecimal("8"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, Integer.valueOf("8"))); + + assertEquals(Boolean.TRUE, DefaultTypeConverter.INSTANCE.convert(Boolean.class, Long.valueOf("1"))); + assertEquals(Boolean.FALSE, DefaultTypeConverter.INSTANCE.convert(Boolean.class, Long.valueOf("0"))); + assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, Long.valueOf("1"))); + assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, Long.valueOf("2"))); + assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, Long.valueOf("3"))); + assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, Long.valueOf("4"))); + assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, Long.valueOf("5"))); + assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, Long.valueOf("6"))); + assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, Long.valueOf("7"))); + assertEquals(new BigDecimal("8"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, Long.valueOf("8"))); + + assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, Float.valueOf("1"))); + assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, Float.valueOf("2"))); + assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, Float.valueOf("3"))); + assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, Float.valueOf("4"))); + assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, Float.valueOf("5"))); + assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, Float.valueOf("6"))); + assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, Float.valueOf("7"))); + + assertEquals(new BigDecimal("8.0"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, Float.valueOf("8"))); + assertTrue(new BigDecimal("8").compareTo(DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, Float.valueOf("8"))) == 0); + + assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, Double.valueOf("1"))); + assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, Double.valueOf("2"))); + assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, Double.valueOf("3"))); + assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, Double.valueOf("4"))); + assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, Double.valueOf("5"))); + assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, Double.valueOf("6"))); + assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, Double.valueOf("7"))); + + assertEquals(new BigDecimal("8.0"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, Double.valueOf("8"))); + assertTrue(new BigDecimal("8").compareTo(DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, Double.valueOf("8"))) == 0); + + assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, new BigInteger("1"))); + assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, new BigInteger("2"))); + assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, new BigInteger("3"))); + assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, new BigInteger("4"))); + assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, new BigInteger("5"))); + assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, new BigInteger("6"))); + assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, new BigInteger("7"))); + assertEquals(new BigDecimal("8"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, new BigInteger("8"))); + + assertEquals(Byte.valueOf("1"), DefaultTypeConverter.INSTANCE.convert(Byte.class, new BigDecimal("1"))); + assertEquals(Short.valueOf("2"), DefaultTypeConverter.INSTANCE.convert(Short.class, new BigDecimal("2"))); + assertEquals(Integer.valueOf("3"), DefaultTypeConverter.INSTANCE.convert(Integer.class, new BigDecimal("3"))); + assertEquals(Long.valueOf("4"), DefaultTypeConverter.INSTANCE.convert(Long.class, new BigDecimal("4"))); + assertEquals(Float.valueOf("5"), DefaultTypeConverter.INSTANCE.convert(Float.class, new BigDecimal("5"))); + assertEquals(Double.valueOf("6"), DefaultTypeConverter.INSTANCE.convert(Double.class, new BigDecimal("6"))); + assertEquals(new BigInteger("7"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, new BigDecimal("7"))); + assertEquals(new BigDecimal("8"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, new BigDecimal("8"))); + } + + public void testDate() + { + Date date = new Date(101); + + assertEquals(Byte.valueOf("101"), DefaultTypeConverter.INSTANCE.convert(Byte.class, date)); + assertEquals(Short.valueOf("101"), DefaultTypeConverter.INSTANCE.convert(Short.class, date)); + assertEquals(Integer.valueOf("101"), DefaultTypeConverter.INSTANCE.convert(Integer.class, date)); + assertEquals(Long.valueOf("101"), DefaultTypeConverter.INSTANCE.convert(Long.class, date)); + assertEquals(Float.valueOf("101"), DefaultTypeConverter.INSTANCE.convert(Float.class, date)); + assertEquals(Double.valueOf("101"), DefaultTypeConverter.INSTANCE.convert(Double.class, date)); + assertEquals(new BigInteger("101"), DefaultTypeConverter.INSTANCE.convert(BigInteger.class, date)); + assertEquals(new BigDecimal("101"), DefaultTypeConverter.INSTANCE.convert(BigDecimal.class, date)); + + assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, (byte)101)); + assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, (short)101)); + assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, (int)101)); + assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, (long)101)); + assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, (float)101)); + assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, (double)101)); + + assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, new BigInteger("101"))); + assertEquals(date, DefaultTypeConverter.INSTANCE.convert(Date.class, (Object)(new BigDecimal("101")))); + + assertEquals(101, DefaultTypeConverter.INSTANCE.intValue(date)); + } + + public void testMultiValue() + { + ArrayList list = makeList(); + + assertEquals(true, DefaultTypeConverter.INSTANCE.isMultiValued(list)); + assertEquals(14, DefaultTypeConverter.INSTANCE.size(list)); + + for(String stringValue: DefaultTypeConverter.INSTANCE.getCollection(String.class, list)) + { + System.out.println("Value is "+stringValue); + } + + } + + private ArrayList makeList() + { + ArrayList list = new ArrayList(); + list.add(Boolean.valueOf(true)); + list.add(Boolean.valueOf(false)); + list.add(Character.valueOf('q')); + list.add(Byte.valueOf("1")); + list.add(Short.valueOf("2")); + list.add(Integer.valueOf("3")); + list.add(Long.valueOf("4")); + list.add(Float.valueOf("5")); + list.add(Double.valueOf("6")); + list.add(new BigInteger("7")); + list.add(new BigDecimal("8")); + list.add(new Date()); + list.add(new Duration("P5Y0M")); + list.add("Hello mum"); + return list; + } + + public void testSingleValuseAsMultiValue() + { + Integer integer = Integer.valueOf(43); + + assertEquals(false, DefaultTypeConverter.INSTANCE.isMultiValued(integer)); + assertEquals(1, DefaultTypeConverter.INSTANCE.size(integer)); + + for(String stringValue: DefaultTypeConverter.INSTANCE.getCollection(String.class, integer)) + { + System.out.println("Value is "+stringValue); + } + + } + + public void testNullAndEmpty() + { + assertNull(DefaultTypeConverter.INSTANCE.convert(Boolean.class, null)); + ArrayList list = new ArrayList(); + assertNotNull(DefaultTypeConverter.INSTANCE.convert(Boolean.class, list)); + list.add(null); + assertNotNull(DefaultTypeConverter.INSTANCE.convert(Boolean.class, list)); + + } +} diff --git a/data-model/src/test/java/org/alfresco/service/cmr/search/StatsProcessorTest.java b/data-model/src/test/java/org/alfresco/service/cmr/search/StatsProcessorTest.java new file mode 100644 index 0000000000..39f8e3d6ae --- /dev/null +++ b/data-model/src/test/java/org/alfresco/service/cmr/search/StatsProcessorTest.java @@ -0,0 +1,120 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.cmr.search; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +public class StatsProcessorTest +{ + + @Test + public void testProcessMap() + { + StatsProcessorUsingMap processor = new StatsProcessorUsingMap(mappingData()); + StatsResultSet input = testData(); + StatsResultSet result = processor.process(input); + assertNotNull(result); + List statsResults= result.getStats(); + assertEquals(5 , statsResults.size()); + assertEquals("Princess" , statsResults.get(0).getName()); + assertEquals("George" , statsResults.get(1).getName()); //if it doesn't find the result then return the original + assertEquals("Queen" , statsResults.get(2).getName()); + assertEquals("Prince" , statsResults.get(3).getName()); + assertEquals("King" , statsResults.get(4).getName()); + } + + private StatsResultSet testData() + { + List stats = new ArrayList<>(); + stats.add(new StatsResultStat("Kate", 1l, 2l, 3l, 4l, 5l)); + stats.add(new StatsResultStat("George", 1l, 2l, 3l, 4l, 5l)); + stats.add(new StatsResultStat("Liz", 1l, 2l, 3l, 4l, 5l)); + stats.add(new StatsResultStat("William", 1l, 2l, 3l, 4l, 5l)); + stats.add(new StatsResultStat("Charles", 1l, 2l, 3l, 4l, 5l)); + + StatsResultSetImpl res = new StatsResultSetImpl( 2l, 3l, 4l, 5l,stats); + return res; + + } + + private Map mappingData() + { + HashMap data = new HashMap<>(); + data.put("Charles", "King"); + data.put("Liz", "Queen"); + data.put("William", "Prince"); + data.put("Kate", "Princess"); + return data; + } + + public static class StatsResultSetImpl implements StatsResultSet { + + private Long numberFound; + private Long sum; + private Long max; + private Long mean; + private List stats; + + public StatsResultSetImpl(Long numberFound, Long sum, Long max, Long mean, + List stats) + { + super(); + this.numberFound = numberFound; + this.sum = sum; + this.max = max; + this.mean = mean; + this.stats = stats; + } + public long getNumberFound() + { + return this.numberFound; + } + public Long getSum() + { + return this.sum; + } + public Long getMax() + { + return this.max; + } + public Long getMean() + { + return this.mean; + } + public List getStats() + { + return this.stats; + } + + } +} diff --git a/data-model/src/test/java/org/alfresco/service/namespace/DynamicNameSpaceResolverTest.java b/data-model/src/test/java/org/alfresco/service/namespace/DynamicNameSpaceResolverTest.java new file mode 100644 index 0000000000..0ffc287b4b --- /dev/null +++ b/data-model/src/test/java/org/alfresco/service/namespace/DynamicNameSpaceResolverTest.java @@ -0,0 +1,148 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.namespace; + +import java.util.Collection; + +import junit.framework.TestCase; + +public class DynamicNameSpaceResolverTest extends TestCase +{ + + public DynamicNameSpaceResolverTest() + { + super(); + } + + public void testOne() + { + DynamicNamespacePrefixResolver dnpr = new DynamicNamespacePrefixResolver(null); + dnpr.registerNamespace("one", "http:/namespace/one"); + dnpr.registerNamespace("two", "http:/namespace/two"); + dnpr.registerNamespace("three", "http:/namespace/three"); + dnpr.registerNamespace("oneagain", "http:/namespace/one"); + dnpr.registerNamespace("four", "http:/namespace/one"); + dnpr.registerNamespace("four", "http:/namespace/four"); + + assertEquals("http:/namespace/one", dnpr.getNamespaceURI("one")); + assertEquals("http:/namespace/two", dnpr.getNamespaceURI("two")); + assertEquals("http:/namespace/three", dnpr.getNamespaceURI("three")); + assertEquals("http:/namespace/one", dnpr.getNamespaceURI("oneagain")); + assertEquals("http:/namespace/four", dnpr.getNamespaceURI("four")); + assertEquals(null, dnpr.getNamespaceURI("five")); + + dnpr.unregisterNamespace("four"); + assertEquals(null, dnpr.getNamespaceURI("four")); + + assertEquals(0, dnpr.getPrefixes("http:/namespace/four").size()); + assertEquals(1, dnpr.getPrefixes("http:/namespace/two").size()); + assertEquals(2, dnpr.getPrefixes("http:/namespace/one").size()); + + + } + + + public void testTwo() + { + DynamicNamespacePrefixResolver dnpr1 = new DynamicNamespacePrefixResolver(null); + dnpr1.registerNamespace("one", "http:/namespace/one"); + dnpr1.registerNamespace("two", "http:/namespace/two"); + dnpr1.registerNamespace("three", "http:/namespace/three"); + dnpr1.registerNamespace("oneagain", "http:/namespace/one"); + dnpr1.registerNamespace("four", "http:/namespace/one"); + dnpr1.registerNamespace("four", "http:/namespace/four"); + dnpr1.registerNamespace("five", "http:/namespace/five"); + dnpr1.registerNamespace("six", "http:/namespace/six"); + + DynamicNamespacePrefixResolver dnpr2 = new DynamicNamespacePrefixResolver(dnpr1); + dnpr2.registerNamespace("a", "http:/namespace/one"); + dnpr2.registerNamespace("b", "http:/namespace/two"); + dnpr2.registerNamespace("c", "http:/namespace/three"); + dnpr2.registerNamespace("d", "http:/namespace/one"); + dnpr2.registerNamespace("e", "http:/namespace/one"); + dnpr2.registerNamespace("f", "http:/namespace/four"); + dnpr2.registerNamespace("five", "http:/namespace/one"); + dnpr2.registerNamespace("six", "http:/namespace/seven"); + + assertEquals("http:/namespace/one", dnpr2.getNamespaceURI("one")); + assertEquals("http:/namespace/two", dnpr2.getNamespaceURI("two")); + assertEquals("http:/namespace/three", dnpr2.getNamespaceURI("three")); + assertEquals("http:/namespace/one", dnpr2.getNamespaceURI("oneagain")); + assertEquals("http:/namespace/four", dnpr2.getNamespaceURI("four")); + assertEquals("http:/namespace/one", dnpr2.getNamespaceURI("five")); + dnpr2.unregisterNamespace("five"); + + assertEquals("http:/namespace/five", dnpr2.getNamespaceURI("five")); + assertEquals("http:/namespace/one", dnpr2.getNamespaceURI("a")); + assertEquals("http:/namespace/two", dnpr2.getNamespaceURI("b")); + assertEquals("http:/namespace/three", dnpr2.getNamespaceURI("c")); + assertEquals("http:/namespace/one", dnpr2.getNamespaceURI("d")); + assertEquals("http:/namespace/one", dnpr2.getNamespaceURI("e")); + assertEquals("http:/namespace/four", dnpr2.getNamespaceURI("f")); + + assertEquals(5, dnpr2.getPrefixes("http:/namespace/one").size()); + assertEquals(2, dnpr2.getPrefixes("http:/namespace/two").size()); + assertEquals(2, dnpr2.getPrefixes("http:/namespace/three").size()); + assertEquals(2, dnpr2.getPrefixes("http:/namespace/four").size()); + assertEquals(1, dnpr2.getPrefixes("http:/namespace/five").size()); + assertEquals(0, dnpr2.getPrefixes("http:/namespace/six").size()); + assertEquals(1, dnpr2.getPrefixes("http:/namespace/seven").size()); + } + + public void testGetters() + { + DynamicNamespacePrefixResolver dnpr = new DynamicNamespacePrefixResolver(new QNameTest.MockNamespacePrefixResolver()); + + dnpr.registerNamespace("one", "http:/namespace/one"); + dnpr.registerNamespace("two", "http:/namespace/two"); + dnpr.registerNamespace("three", "http:/namespace/three"); + dnpr.registerNamespace("oneagain", "http:/namespace/one"); + dnpr.registerNamespace("four", "http:/namespace/one"); + dnpr.registerNamespace("four", "http:/namespace/four"); + dnpr.registerNamespace("five", "http:/namespace/five"); + dnpr.registerNamespace("six", "http:/namespace/six"); + + Collection prefixes = dnpr.getPrefixes(); + assertNotNull(prefixes); + assertTrue(prefixes.contains("one")); + assertTrue(prefixes.contains("two")); + assertTrue(prefixes.contains("three")); + assertTrue(prefixes.contains("four")); + assertTrue(prefixes.contains("five")); + assertTrue(prefixes.contains("six")); + assertTrue(prefixes.contains("oneagain")); + + Collection uris = dnpr.getURIs(); + assertNotNull(uris); + assertTrue(uris.contains("http:/namespace/one")); + assertTrue(uris.contains("http:/namespace/two")); + assertTrue(uris.contains("http:/namespace/three")); + assertTrue(uris.contains("http:/namespace/four")); + assertTrue(uris.contains("http:/namespace/five")); + assertTrue(uris.contains("http:/namespace/six")); + } + +} diff --git a/data-model/src/test/java/org/alfresco/service/namespace/QNamePatternTest.java b/data-model/src/test/java/org/alfresco/service/namespace/QNamePatternTest.java new file mode 100644 index 0000000000..be8796c0a0 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/service/namespace/QNamePatternTest.java @@ -0,0 +1,80 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.namespace; + + +import junit.framework.TestCase; + +/** + * Tests the various implementations of the + * {@link org.alfresco.service.namespace.QNamePattern}. + * + * @author Derek Hulley + */ +public class QNamePatternTest extends TestCase +{ + private static final String TEST_NAMESPACE = "http://www.alfresco.org/QNamePatternTest"; + + QName check1; + QName check2; + QName check3; + + public QNamePatternTest(String name) + { + super(name); + } + + public void setUp() throws Exception + { + check1 = QName.createQName(null, "ABC"); + check2 = QName.createQName(TEST_NAMESPACE, "XYZ"); + check3 = QName.createQName(TEST_NAMESPACE, "ABC"); + } + + public void testSimpleQNamePattern() throws Exception + { + QNamePattern pattern = QName.createQName(TEST_NAMESPACE, "ABC"); + + // check + assertFalse("Simple match failed: " + check1, pattern.isMatch(check1)); + assertFalse("Simple match failed: " + check2, pattern.isMatch(check2)); + assertTrue("Simple match failed: " + check3, pattern.isMatch(check3)); + } + + public void testRegexQNamePatternMatcher() throws Exception + { + QNamePattern pattern = new RegexQNamePattern(".*alfresco.*", "A.?C"); + + // check + assertFalse("Regex match failed: " + check1, pattern.isMatch(check1)); + assertFalse("Regex match failed: " + check2, pattern.isMatch(check2)); + assertTrue("Regex match failed: " + check3, pattern.isMatch(check3)); + + assertTrue("All match failed: " + check1, RegexQNamePattern.MATCH_ALL.isMatch(check1)); + assertTrue("All match failed: " + check2, RegexQNamePattern.MATCH_ALL.isMatch(check2)); + assertTrue("All match failed: " + check3, RegexQNamePattern.MATCH_ALL.isMatch(check3)); + } +} diff --git a/data-model/src/test/java/org/alfresco/service/namespace/QNameTest.java b/data-model/src/test/java/org/alfresco/service/namespace/QNameTest.java new file mode 100644 index 0000000000..cfd7101bb9 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/service/namespace/QNameTest.java @@ -0,0 +1,282 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.service.namespace; + +import java.util.Collection; +import java.util.HashSet; + +import junit.framework.TestCase; + + + +/** + * @see org.alfresco.service.namespace.QName + * + * @author David Caruana + */ +public class QNameTest extends TestCase +{ + + public QNameTest(String name) + { + super(name); + } + + + public void testInvalidQName() throws Exception + { + try + { + QName qname = QName.createQName(""); + fail("Missing local name was not caught"); + } + catch (InvalidQNameException e) + { + } + + try + { + QName qname = QName.createQName("invalid{}name"); + fail("Namespace not at start was not caught"); + } + catch (InvalidQNameException e) + { + } + + try + { + QName qname = QName.createQName("{name"); + fail("Missing closing namespace token was not caught"); + } + catch (InvalidQNameException e) + { + } + + try + { + QName qname = QName.createQName("{}"); + fail("Missing local name after namespace was not caught"); + } + catch (InvalidQNameException e) + { + } + + try + { + QName qname = QName.createQName("{}name"); + } + catch (InvalidQNameException e) + { + fail("Empty namespace is valid"); + } + + try + { + QName qname = QName.createQName("{namespace}name"); + assertEquals("namespace", qname.getNamespaceURI()); + assertEquals("name", qname.getLocalName()); + } + catch (InvalidQNameException e) + { + fail("Valid namespace has been thrown out"); + } + + try + { + QName qname = QName.createQName((String) null, (String) null); + fail("Null name was not caught"); + } + catch (InvalidQNameException e) + { + } + + try + { + QName qname = QName.createQName((String) null, ""); + fail("Empty name was not caught"); + } + catch (InvalidQNameException e) + { + } + + } + + + public void testConstruction() + { + QName qname1 = QName.createQName("namespace1", "name1"); + assertEquals("namespace1", qname1.getNamespaceURI()); + assertEquals("name1", qname1.getLocalName()); + + QName qname2 = QName.createQName("{namespace2}name2"); + assertEquals("namespace2", qname2.getNamespaceURI()); + assertEquals("name2", qname2.getLocalName()); + + QName qname3 = QName.createQName(null, "name3"); + assertEquals("", qname3.getNamespaceURI()); + + QName qname4 = QName.createQName("", "name4"); + assertEquals("", qname4.getNamespaceURI()); + + QName qname5 = QName.createQName("{}name5"); + assertEquals("", qname5.getNamespaceURI()); + + QName qname6 = QName.createQName("name6"); + assertEquals("", qname6.getNamespaceURI()); + } + + + public void testStringRepresentation() + { + QName qname1 = QName.createQName("namespace", "name1"); + assertEquals("{namespace}name1", qname1.toString()); + + QName qname2 = QName.createQName("", "name2"); + assertEquals("{}name2", qname2.toString()); + + QName qname3 = QName.createQName("{namespace}name3"); + assertEquals("{namespace}name3", qname3.toString()); + + QName qname4 = QName.createQName("{}name4"); + assertEquals("{}name4", qname4.toString()); + + QName qname5 = QName.createQName("name5"); + assertEquals("{}name5", qname5.toString()); + } + + public void testCommonTypes() + { + QName qname3 = QName.createQName("{http://www.alfresco.org/model/content/1.0}created"); + assertEquals("{http://www.alfresco.org/model/content/1.0}created", qname3.toString()); + + QName qname4 = QName.createQName("{http://www.alfresco.org/model/content/1.0}creator.__"); + assertEquals("{http://www.alfresco.org/model/content/1.0}creator.__", qname4.toString()); + + QName qname5 = QName.createQName("{http://www.alfresco.org/model/content/1.0}content.mimetype"); + assertEquals("{http://www.alfresco.org/model/content/1.0}content.mimetype", qname5.toString()); + } + + public void testEquality() + { + QName qname1 = QName.createQName("namespace", "name"); + QName qname2 = QName.createQName("namespace", "name"); + QName qname3 = QName.createQName("{namespace}name"); + assertEquals(qname1, qname2); + assertEquals(qname1, qname3); + assertEquals(qname1.hashCode(), qname2.hashCode()); + assertEquals(qname1.hashCode(), qname3.hashCode()); + + QName qname4 = QName.createQName("", "name"); + QName qname5 = QName.createQName("", "name"); + QName qname6 = QName.createQName(null, "name"); + assertEquals(qname4, qname5); + assertEquals(qname4, qname6); + assertEquals(qname4.hashCode(), qname5.hashCode()); + assertEquals(qname4.hashCode(), qname6.hashCode()); + + QName qname7 = QName.createQName("namespace", "name"); + QName qname8 = QName.createQName("namespace", "differentname"); + assertFalse(qname7.equals(qname8)); + assertFalse(qname7.hashCode() == qname8.hashCode()); + + QName qname9 = QName.createQName("namespace", "name"); + QName qname10 = QName.createQName("differentnamespace", "name"); + assertFalse(qname9.equals(qname10)); + assertFalse(qname9.hashCode() == qname10.hashCode()); + } + + + public void testPrefix() + { + try + { + QName noResolver = QName.createQName(NamespaceService.ALFRESCO_PREFIX, "alfresco prefix", null); + fail("Null resolver was not caught"); + } + catch (IllegalArgumentException e) + { + } + + NamespacePrefixResolver mockResolver = new MockNamespacePrefixResolver(); + QName qname1 = QName.createQName(NamespaceService.ALFRESCO_PREFIX, "alfresco prefix", mockResolver); + assertEquals(NamespaceService.ALFRESCO_URI, qname1.getNamespaceURI()); + QName qname2 = QName.createQName("", "default prefix", mockResolver); + assertEquals(NamespaceService.DEFAULT_URI, qname2.getNamespaceURI()); + QName qname3 = QName.createQName(null, "null default prefix", mockResolver); + assertEquals(NamespaceService.DEFAULT_URI, qname3.getNamespaceURI()); + + try + { + QName qname4 = QName.createQName("garbage", "garbage prefix", mockResolver); + fail("Invalid Prefix was not caught"); + } + catch (NamespaceException e) + { + } + } + + + public static class MockNamespacePrefixResolver + implements NamespacePrefixResolver + { + + public String getNamespaceURI(String prefix) + { + if (prefix.equals(NamespaceService.DEFAULT_PREFIX)) + { + return NamespaceService.DEFAULT_URI; + } + else if (prefix.equals(NamespaceService.ALFRESCO_PREFIX)) + { + return NamespaceService.ALFRESCO_URI; + } + throw new NamespaceException("Prefix " + prefix + " not registered"); + } + + public Collection getPrefixes(String namespaceURI) + { + throw new NamespaceException("URI " + namespaceURI + " not registered"); + } + + public Collection getPrefixes() + { + HashSet prefixes = new HashSet(); + prefixes.add(NamespaceService.DEFAULT_PREFIX); + prefixes.add(NamespaceService.ALFRESCO_PREFIX); + return prefixes; + } + + public Collection getURIs() + { + HashSet uris = new HashSet(); + uris.add(NamespaceService.DEFAULT_URI); + uris.add(NamespaceService.ALFRESCO_URI); + return uris; + } + + } + +} diff --git a/data-model/src/test/java/org/alfresco/util/ISO9075Test.java b/data-model/src/test/java/org/alfresco/util/ISO9075Test.java new file mode 100644 index 0000000000..87994feed2 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/util/ISO9075Test.java @@ -0,0 +1,151 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +import junit.framework.TestCase; + +public class ISO9075Test extends TestCase +{ + + public ISO9075Test() + { + super(); + } + + public ISO9075Test(String arg0) + { + super(arg0); + } + + public void testEncoding() + { + assertEquals("My2Documents", ISO9075.encode("My2Documents")); + assertEquals("My_x002f_Documents", ISO9075.encode("My/Documents")); + assertEquals("My_Documents", ISO9075.encode("My_Documents")); + assertEquals("My_x0020_Documents", ISO9075.encode("My Documents")); + assertEquals("My_x0020Documents", ISO9075.encode("My_x0020Documents")); + assertEquals("My_x005f_x0020_Documents", ISO9075.encode("My_x0020_Documents")); + assertEquals("_x005f_x0020_Documents", ISO9075.encode("_x0020_Documents")); + assertEquals("_x0040__x005f_x0020_Documents", ISO9075.encode("@_x0020_Documents")); + assertEquals("Andy_x0027_s_x0020_Bits_x0020__x0026__x0020_Bobs_x0020__xabcd__x005c_", ISO9075 + .encode("Andy's Bits & Bobs \uabcd\\")); + assertEquals( + "_x0020__x0060__x00ac__x00a6__x0021__x0022__x00a3__x0024__x0025__x005e__x0026__x002a__x0028__x0029_-__x003d__x002b__x0009__x000a__x005c__x0000__x005b__x005d__x007b__x007d__x003b__x0027__x0023__x003a__x0040__x007e__x002c_._x002f__x003c__x003e__x003f__x005c__x007c_", + ISO9075.encode(" `\u00ac\u00a6!\"\u00a3$%^&*()-_=+\t\n\\\u0000[]{};'#:@~,./<>?\\|")); + assertEquals("\u0123_x4567_\u8900_xabcd__xefff__xT65A_", ISO9075 + .encode("\u0123\u4567\u8900\uabcd\uefff_xT65A_")); + assertEquals("_x003a_", ISO9075.encode(":")); + } + + public void testDeEncoding() + { + assertEquals("MyDocuments", ISO9075.decode("MyDocuments")); + assertEquals("My_Documents", ISO9075.decode("My_Documents")); + assertEquals("My Documents", ISO9075.decode("My_x0020_Documents")); + assertEquals("My_x0020Documents", ISO9075.decode("My_x0020Documents")); + assertEquals("My_x0020_Documents", ISO9075.decode("My_x005f_x0020_Documents")); + assertEquals("_x0020_Documents", ISO9075.decode("_x005f_x0020_Documents")); + assertEquals("@_x0020_Documents", ISO9075.decode("_x0040__x005f_x0020_Documents")); + assertEquals("Andy's Bits & Bobs \uabcd", ISO9075 + .decode("Andy_x0027_s_x0020_Bits_x0020__x0026__x0020_Bobs_x0020__xabcd_")); + assertEquals("Andy's Bits & Bobs \uabcd\\", ISO9075 + .decode("Andy_x0027_s_x0020_Bits_x0020__x0026__x0020_Bobs_x0020__xabcd__x005c_")); + assertEquals( + " `\u00ac\u00a6!\"\u00a3$%^&*()-_=+\t\n\\\u0000[]{};'#:@~,./<>?\\|", + ISO9075 + .decode("_x0020__x0060__x00ac__x00a6__x0021__x0022__x00a3__x0024__x0025__x005e__x0026__x002a__x0028__x0029_-__x003d__x002b__x0009__x000a__x005c__x0000__x005b__x005d__x007b__x007d__x003b__x0027__x0023__x003a__x0040__x007e__x002c_._x002f__x003c__x003e__x003f__x005c__x007c_")); + assertEquals("\u0123\u4567\u8900\uabcd\uefff_xT65A_", ISO9075 + .decode("\u0123_x4567_\u8900_xabcd__xefff__xT65A_")); + } + + public void testDeEncodingUpperCase() + { + + assertEquals("My_x0020_Documents", ISO9075.decode("My_x005F_x0020_Documents")); + assertEquals("_x0020_Documents", ISO9075.decode("_x005F_x0020_Documents")); + assertEquals("@_x0020_Documents", ISO9075.decode("_x0040__x005F_x0020_Documents")); + assertEquals("Andy's Bits & Bobs \uabcd\\", ISO9075 + .decode("Andy_x0027_s_x0020_Bits_x0020__x0026__x0020_Bobs_x0020__xabcd__x005C_")); + assertEquals( + " `\u00ac\u00a6!\"\u00a3$%^&*()-_=+\t\n\\\u0000[]{};'#:@~,./<>?\\|", + ISO9075 + .decode("_x0020__x0060__x00AC__x00A6__x0021__x0022__x00A3__x0024__x0025__x005E__x0026__x002A__x0028__x0029_-__x003D__x002B__x0009__x000A__x005C__x0000__x005B__x005D__x007B__x007D__x003B__x0027__x0023__x003A__x0040__x007E__x002C_._x002F__x003C__x003E__x003F__x005C__x007C_")); + assertEquals("\u0123\u4567\u8900\uabcd\uefff_xT65A_", ISO9075 + .decode("\u0123_x4567_\u8900_xABCD__xEFFF__xT65A_")); + } + + public void testRoundTrip1() + { + assertEquals("MyDocuments", ISO9075.decode(ISO9075.encode("MyDocuments"))); + assertEquals("My_Documents", ISO9075.decode(ISO9075.encode("My_Documents"))); + assertEquals("My Documents", ISO9075.decode(ISO9075.encode("My Documents"))); + assertEquals("My_x0020Documents", ISO9075.decode(ISO9075.encode("My_x0020Documents"))); + assertEquals("My_x0020_Documents", ISO9075.decode(ISO9075.encode("My_x0020_Documents"))); + assertEquals("_x0020_Documents", ISO9075.decode(ISO9075.encode("_x0020_Documents"))); + assertEquals("@_x0020_Documents", ISO9075.decode(ISO9075.encode("@_x0020_Documents"))); + assertEquals("Andy's Bits & Bobs \uabcd", ISO9075.decode(ISO9075.encode("Andy's Bits & Bobs \uabcd"))); + assertEquals("Andy's Bits & Bobs \uabcd\\", ISO9075.decode(ISO9075.encode("Andy's Bits & Bobs \uabcd\\"))); + assertEquals( + " `\u00ac\u00a6!\"\u00a3$%^&*()-_=+\t\n\\\u0000[]{};'#:@~,./<>?\\|", + ISO9075.decode(ISO9075.encode(" `\u00ac\u00a6!\"\u00a3$%^&*()-_=+\t\n\\\u0000[]{};'#:@~,./<>?\\|"))); + assertEquals("\u0123\u4567\u8900\uabcd\uefff_xT65A_", ISO9075.decode(ISO9075.encode("\u0123\u4567\u8900\uabcd\uefff_xT65A_"))); + } + + public void testRoundTrip2() + { + assertEquals("MyDocuments", ISO9075.encode(ISO9075.decode("MyDocuments"))); + assertEquals("My_Documents", ISO9075.encode(ISO9075.decode("My_Documents"))); + assertEquals("My_x0020_Documents", ISO9075.encode(ISO9075.decode("My_x0020_Documents"))); + assertEquals("My_x0020Documents", ISO9075.encode(ISO9075.decode("My_x0020Documents"))); + assertEquals("My_x005f_x0020_Documents", ISO9075.encode(ISO9075.decode("My_x005f_x0020_Documents"))); + assertEquals("_x005f_x0020_Documents", ISO9075.encode(ISO9075.decode("_x005f_x0020_Documents"))); + assertEquals("_x0040__x005f_x0020_Documents", ISO9075.encode(ISO9075.decode("_x0040__x005f_x0020_Documents"))); + assertEquals("Andy_x0027_s_x0020_Bits_x0020__x0026__x0020_Bobs_x0020__xabcd_", ISO9075.encode(ISO9075 + .decode("Andy_x0027_s_x0020_Bits_x0020__x0026__x0020_Bobs_x0020__xabcd_"))); + assertEquals("Andy_x0027_s_x0020_Bits_x0020__x0026__x0020_Bobs_x0020__xabcd__x005c_", ISO9075.encode(ISO9075 + .decode("Andy_x0027_s_x0020_Bits_x0020__x0026__x0020_Bobs_x0020__xabcd__x005c_"))); + assertEquals( + "_x0020__x0060__x00ac__x00a6__x0021__x0022__x00a3__x0024__x0025__x005e__x0026__x002a__x0028__x0029_-__x003d__x002b__x0009__x000a__x005c__x0000__x005b__x005d__x007b__x007d__x003b__x0027__x0023__x003a__x0040__x007e__x002c_._x002f__x003c__x003e__x003f__x005c__x007c_", + ISO9075.encode(ISO9075 + .decode("_x0020__x0060__x00ac__x00a6__x0021__x0022__x00a3__x0024__x0025__x005e__x0026__x002a__x0028__x0029_-__x003d__x002b__x0009__x000a__x005c__x0000__x005b__x005d__x007b__x007d__x003b__x0027__x0023__x003a__x0040__x007e__x002c_._x002f__x003c__x003e__x003f__x005c__x007c_"))); + assertEquals("\u0123_x4567_\u8900_xabcd__xefff__xT65A_", ISO9075.encode(ISO9075 + .decode("\u0123_x4567_\u8900_xabcd__xefff__xT65A_"))); + } + + public void testJira_ALF_8554() + { + assertEquals("a_x0020", ISO9075.decode("a_x0020")); + } + + public void testEncodeSQL() + { + assertEquals("vns10:individual_entity", ISO9075.encodeSQL("vns10:individual_entity")); + assertEquals("_vns10:individual_entity", ISO9075.encodeSQL("_vns10:individual_entity")); + assertEquals("_x0031_vns10:individual_entity", ISO9075.encodeSQL("1vns10:individual_entity")); + assertEquals("_x0031_vns10:individual_x002d_entity", ISO9075.encodeSQL("1vns10:individual-entity")); + } + +} diff --git a/data-model/src/test/java/org/alfresco/util/NumericEncodingTest.java b/data-model/src/test/java/org/alfresco/util/NumericEncodingTest.java new file mode 100644 index 0000000000..e4e3c5d88b --- /dev/null +++ b/data-model/src/test/java/org/alfresco/util/NumericEncodingTest.java @@ -0,0 +1,222 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +import junit.framework.TestCase; + +/** + * Tests for string encoding + * @author andyh + * + */ +public class NumericEncodingTest extends TestCase +{ + + /** + * + * + */ + public NumericEncodingTest() + { + super(); + } + + /** + * + * @param arg0 String + */ + public NumericEncodingTest(String arg0) + { + super(arg0); + } + + /** + * Do an exhaustive test for integers + * + */ + public void xtestAllIntegerEncodings() + { + String lastString = null; + String nextString = null; + for (long i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i++) + { + nextString = NumericEncoder.encode((int) i); + if (lastString != null) + { + assertFalse(lastString.compareTo(nextString) > 0); + } + lastString = nextString; + } + } + + /** + * Do an exhaustive test for float + * + */ + public void xtestAllFloatEncodings() + { + Float last = null; + Float next = null; + String lastString = null; + String nextString = null; + + for (int sign = 1; sign >= 0; sign--) + { + if (sign == 0) + { + for (int exponent = 0; exponent <= 0xFF; exponent++) + { + for (int mantissa = 0; mantissa <= 0x007FFFFF; mantissa++) + { + int bitPattern = sign << 31 | exponent << 23 | mantissa; + next = Float.intBitsToFloat(bitPattern); + + if (!next.equals(Float.NaN) && (last != null) && (last.compareTo(next) > 0)) + { + System.err.println(last + " > " + next); + } + if (!next.equals(Float.NaN)) + { + nextString = NumericEncoder.encode(next); + if ((lastString != null) && (lastString.compareTo(nextString) > 0)) + { + System.err.println(lastString + " > " + nextString); + } + lastString = nextString; + } + last = next; + + } + } + } + else + { + for (int exponent = 0xFF; exponent >= 0; exponent--) + { + for (int mantissa = 0x007FFFFF; mantissa >= 0; mantissa--) + { + int bitPattern = sign << 31 | exponent << 23 | mantissa; + next = Float.intBitsToFloat(bitPattern); + if (!next.equals(Float.NaN) && (last != null) && (last.compareTo(next) > 0)) + { + System.err.println(last + " > " + next); + } + if (!next.equals(Float.NaN)) + { + nextString = NumericEncoder.encode(next); + if ((lastString != null) && (lastString.compareTo(nextString) > 0)) + { + System.err.println(lastString + " > " + nextString); + } + lastString = nextString; + } + last = next; + } + } + } + } + } + + /** + * Sample test for int + */ + + public void testIntegerEncoding() + { + assertEquals("00000000", NumericEncoder.encode(Integer.MIN_VALUE)); + assertEquals("00000001", NumericEncoder.encode(Integer.MIN_VALUE + 1)); + assertEquals("7fffffff", NumericEncoder.encode(-1)); + assertEquals("80000000", NumericEncoder.encode(0)); + assertEquals("80000001", NumericEncoder.encode(1)); + assertEquals("fffffffe", NumericEncoder.encode(Integer.MAX_VALUE - 1)); + assertEquals("ffffffff", NumericEncoder.encode(Integer.MAX_VALUE)); + } + + /** + * Sample test for long + */ + + public void testLongEncoding() + { + assertEquals("0000000000000000", NumericEncoder.encode(Long.MIN_VALUE)); + assertEquals("0000000000000001", NumericEncoder.encode(Long.MIN_VALUE + 1)); + assertEquals("7fffffffffffffff", NumericEncoder.encode(-1L)); + assertEquals("8000000000000000", NumericEncoder.encode(0L)); + assertEquals("8000000000000001", NumericEncoder.encode(1L)); + assertEquals("fffffffffffffffe", NumericEncoder.encode(Long.MAX_VALUE - 1)); + assertEquals("ffffffffffffffff", NumericEncoder.encode(Long.MAX_VALUE)); + + assertEquals(NumericEncoder.decodeLong(NumericEncoder.encode(Long.MIN_VALUE)), Long.MIN_VALUE); + assertEquals(NumericEncoder.decodeLong(NumericEncoder.encode(Long.MIN_VALUE + 1)),Long.MIN_VALUE + 1); + assertEquals(NumericEncoder.decodeLong(NumericEncoder.encode(-1L)), -1L); + assertEquals(NumericEncoder.decodeLong(NumericEncoder.encode(0L)), 0L); + assertEquals(NumericEncoder.decodeLong(NumericEncoder.encode(1L)), 1L); + assertEquals(NumericEncoder.decodeLong(NumericEncoder.encode(Long.MAX_VALUE - 1)),Long.MAX_VALUE - 1); + assertEquals(NumericEncoder.decodeLong(NumericEncoder.encode(Long.MAX_VALUE)), Long.MAX_VALUE); + } + + /** + * Sample test for float + */ + + public void testFloatEncoding() + { + assertEquals("007fffff", NumericEncoder.encode(Float.NEGATIVE_INFINITY)); + assertEquals("00800000", NumericEncoder.encode(-Float.MAX_VALUE)); + assertEquals("7ffffffe", NumericEncoder.encode(-Float.MIN_VALUE)); + assertEquals("7fffffff", NumericEncoder.encode(-0f)); + assertEquals("80000000", NumericEncoder.encode(0f)); + assertEquals("80000001", NumericEncoder.encode(Float.MIN_VALUE)); + assertEquals("ff7fffff", NumericEncoder.encode(Float.MAX_VALUE)); + assertEquals("ff800000", NumericEncoder.encode(Float.POSITIVE_INFINITY)); + assertEquals("ffc00000", NumericEncoder.encode(Float.NaN)); + + } + + /** + * Sample test for double + */ + + public void testDoubleEncoding() + { + assertEquals("000fffffffffffff", NumericEncoder.encode(Double.NEGATIVE_INFINITY)); + assertEquals("0010000000000000", NumericEncoder.encode(-Double.MAX_VALUE)); + assertEquals("7ffffffffffffffe", NumericEncoder.encode(-Double.MIN_VALUE)); + assertEquals("7fffffffffffffff", NumericEncoder.encode(-0d)); + assertEquals("8000000000000000", NumericEncoder.encode(0d)); + assertEquals("8000000000000001", NumericEncoder.encode(Double.MIN_VALUE)); + assertEquals("ffefffffffffffff", NumericEncoder.encode(Double.MAX_VALUE)); + assertEquals("fff0000000000000", NumericEncoder.encode(Double.POSITIVE_INFINITY)); + assertEquals("fff8000000000000", NumericEncoder.encode(Double.NaN)); + + assertTrue( NumericEncoder.encode(-0.9).compareTo(NumericEncoder.encode(0.88)) < 0); + assertTrue( NumericEncoder.encode(-0.9).compareTo(NumericEncoder.encode(0.91)) < 0); + assertTrue( NumericEncoder.encode(0.88).compareTo(NumericEncoder.encode(0.91)) < 0); + + + + } +} diff --git a/data-model/src/test/java/org/alfresco/util/SearchDateConversionTest.java b/data-model/src/test/java/org/alfresco/util/SearchDateConversionTest.java new file mode 100644 index 0000000000..ea27177f04 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/util/SearchDateConversionTest.java @@ -0,0 +1,173 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2017 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +import static org.junit.Assert.*; +import org.alfresco.service.cmr.search.IntervalSet; +import org.joda.time.DateTimeZone; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.extensions.surf.util.I18NUtil; + +import java.io.UnsupportedEncodingException; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +/** + * Basic calls + */ +public class SearchDateConversionTest +{ + SearchDateConversion subject = new SearchDateConversion(); + + @Test + public void parseDateString() throws Exception + { + setDefaults(); + Pair result = subject.parseDateString("2017"); + assertEquals(Calendar.YEAR, result.getSecond().intValue()); + assertEquals(1483228800000l, result.getFirst().getTime()); + + result = subject.parseDateString("2017-12"); + assertEquals(Calendar.MONTH, result.getSecond().intValue()); + assertEquals(1512086400000l, result.getFirst().getTime()); + + result = subject.parseDateString("2017-12-12"); + assertEquals(Calendar.DAY_OF_MONTH, result.getSecond().intValue()); + assertEquals(1513036800000l, result.getFirst().getTime()); + + result = subject.parseDateString("NOW"); + assertEquals(Calendar.MILLISECOND, result.getSecond().intValue()); + + result = subject.parseDateString("MIN"); + assertEquals(Calendar.MILLISECOND, result.getSecond().intValue()); + + result = subject.parseDateString("TODAY"); + assertEquals(Calendar.DAY_OF_MONTH, result.getSecond().intValue()); + + result = subject.parseDateString("MAX"); + assertEquals(Calendar.MILLISECOND, result.getSecond().intValue()); + + result = subject.parseDateString("NONSENSE"); + assertNull(result); + + result = subject.parseDateString("NOW/YEAR"); + assertNull(result); + + result = subject.parseDateString("*"); + assertNull(result); + } + + @Test + public void getDateEnd() throws Exception + { + setDefaults(); + Pair result = subject.parseDateString("2017-12"); + assertEquals("2017-12-31T23:59:59.999Z", subject.getDateEnd(result)); + + result = subject.parseDateString("2017-12-12"); + assertEquals("2017-12-12T23:59:59.999Z", subject.getDateEnd(result)); + + result = subject.parseDateString("2017"); + assertEquals("2017-12-31T23:59:59.999Z", subject.getDateEnd(result)); + } + + @Test + public void getDateStart() throws Exception + { + setDefaults(); + Pair result = subject.parseDateString("2017-12"); + assertEquals("2017-12-01T00:00:00.000Z", subject.getDateStart(result)); + + result = subject.parseDateString("2017-12-12"); + assertEquals("2017-12-12T00:00:00.000Z", subject.getDateStart(result)); + + result = subject.parseDateString("2017"); + assertEquals("2017-01-01T00:00:00.000Z", subject.getDateStart(result)); + } + + @Test + public void testIntervalDates() throws UnsupportedEncodingException + { + setDefaults(); + IntervalSet intervalSet = new IntervalSet("1", "10", "just numbers", false, true); + IntervalSet validated = subject.parseDateInterval(intervalSet, false); + assertEquals(intervalSet, validated); + + intervalSet = new IntervalSet("2006", "2010", "years", true, true); + validated = subject.parseDateInterval(intervalSet, true); + assertEquals("2006-01-01T00:00:00.000Z", validated.getStart()); + assertTrue(validated.isStartInclusive()); + assertEquals("2010-12-31T23:59:59.999Z", validated.getEnd()); + assertTrue(validated.isEndInclusive()); + + intervalSet = new IntervalSet("2006", "2010", "years", false, false); + validated = subject.parseDateInterval(intervalSet, true); + assertEquals("2006-12-31T23:59:59.999Z", validated.getStart()); + assertFalse(validated.isStartInclusive()); + assertEquals("2010-01-01T00:00:00.000Z", validated.getEnd()); + assertFalse(validated.isEndInclusive()); + + intervalSet = new IntervalSet("2006-09", "2010-03", "months", true, true); + validated = subject.parseDateInterval(intervalSet, true); + assertEquals("2006-09-01T00:00:00.000Z", validated.getStart()); + assertTrue(validated.isStartInclusive()); + assertEquals("2010-03-31T23:59:59.999Z", validated.getEnd()); + assertTrue(validated.isEndInclusive()); + + intervalSet = new IntervalSet("2006-09", "2010-03", "months", false, false); + validated = subject.parseDateInterval(intervalSet, true); + assertEquals("2006-09-30T23:59:59.999Z", validated.getStart()); + assertFalse(validated.isStartInclusive()); + assertEquals("2010-03-01T00:00:00.000Z", validated.getEnd()); + assertFalse(validated.isEndInclusive()); + + intervalSet = new IntervalSet("2017-09-01", "2017-09-30", "sept", true, true); + validated = subject.parseDateInterval(intervalSet, true); + assertEquals("2017-09-01T00:00:00.000Z", validated.getStart()); + assertTrue(validated.isStartInclusive()); + assertEquals("2017-09-30T23:59:59.999Z", validated.getEnd()); + assertTrue(validated.isEndInclusive()); + + intervalSet = new IntervalSet("2017-08-31", "2017-10-01", "sept", false, false); + validated = subject.parseDateInterval(intervalSet, true); + assertEquals("2017-08-31T23:59:59.999Z", validated.getStart()); + assertFalse(validated.isStartInclusive()); + assertEquals("2017-10-01T00:00:00.000Z", validated.getEnd()); + assertFalse(validated.isEndInclusive()); + } + + + protected void setDefaults() + { + DateTimeZone.setDefault(DateTimeZone.UTC); //Joda + Locale.setDefault(Locale.UK); + TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + } +} \ No newline at end of file diff --git a/data-model/src/test/java/org/alfresco/util/SearchLanguageConversionTest.java b/data-model/src/test/java/org/alfresco/util/SearchLanguageConversionTest.java new file mode 100644 index 0000000000..98c239a898 --- /dev/null +++ b/data-model/src/test/java/org/alfresco/util/SearchLanguageConversionTest.java @@ -0,0 +1,161 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +import junit.framework.TestCase; + +/** + * @see org.alfresco.util.SearchLanguageConversion + * + * @author Derek Hulley + */ +public class SearchLanguageConversionTest extends TestCase +{ + /** + * A string with a whole lod of badness to stress test with + */ + private static final String BAD_STRING = + "\\ | ! \" £ " + + "$ % ^ & * ( " + + ") _ { } [ ] " + + "@ # ~ ' : ; " + + ", . < > + ? " + + "/ \\\\ \\* \\? \\_"; + + public void testEscapeXPathLike() + { + String good = SearchLanguageConversion.escapeForXPathLike(BAD_STRING); + assertEquals("Escaping for xpath failed", + "\\\\ | ! \" £ " + + "$ \\% ^ & * ( " + + ") \\_ { } \\[ \\] " + + "@ # ~ ' : ; " + + ", . < > + ? " + + "/ \\\\\\\\ \\\\* \\\\? \\\\\\_", + good); + } + + public void testEscapeRegex() + { + String good = SearchLanguageConversion.escapeForRegex(BAD_STRING); + assertEquals("Escaping for regex failed", + "\\\\ \\| ! \" £ " + + "\\$ % \\^ & \\* \\( " + + "\\) _ \\{ \\} \\[ \\] " + + "@ # ~ ' : ; " + + ", \\. < > \\+ \\? " + + "/ \\\\\\\\ \\\\\\* \\\\\\? \\\\_", + good); + } + + public void testEscapeLucene() + { + String good = SearchLanguageConversion.escapeForLucene(BAD_STRING); + assertEquals("Escaping for Lucene failed", + "\\\\ \\| \\! \\\" £ " + + "$ % \\^ \\& \\* \\( " + + "\\) _ \\{ \\} \\[ \\] " + + "@ # \\~ ' \\: ; " + + ", . < > \\+ \\? " + + "\\/ \\\\\\\\ \\\\\\* \\\\\\? \\\\_", + good); + } + + public void testConvertXPathLikeToRegex() + { + String good = SearchLanguageConversion.convertXPathLikeToRegex(BAD_STRING); + assertEquals("XPath like to regex failed", + "(?s) \\| ! \" £ " + + "\\$ .* \\^ & \\* \\( " + + "\\) . \\{ \\} \\[ \\] " + + "@ # ~ ' : ; " + + ", \\. < > \\+ \\? " + + "/ \\\\ \\* \\? _", + good); + } + + public void testConvertXPathLikeToLucene() + { + String good = SearchLanguageConversion.convertXPathLikeToLucene(BAD_STRING); + assertEquals("XPath like to Lucene failed", + " \\| \\! \\\" £ " + + "$ * \\^ \\& \\* \\( " + + "\\) ? \\{ \\} \\[ \\] " + + "@ # \\~ ' \\: ; " + + ", . < > \\+ \\? " + + "\\/ \\\\ \\* \\? _", + good); + } + + public void testSqlToLucene() + { + String sqlLike = "AB%_*?\\%\\_"; + String lucene = "AB*?\\*\\?%_"; + String converted = SearchLanguageConversion.convert(SearchLanguageConversion.DEF_SQL_LIKE, SearchLanguageConversion.DEF_LUCENE, sqlLike); + assertEquals(lucene, converted); + } + + public void testLuceneToRegexp() + { + String lucene = "AB*?\\*\\?.*."; + String regexp = "AB.*.\\*\\?\\..*\\."; + String converted = SearchLanguageConversion.convert(SearchLanguageConversion.DEF_LUCENE, SearchLanguageConversion.DEF_REGEX, lucene); + assertEquals(regexp, converted); + } + + public void testLuceneToSql() + { + String lucene = "%_"; + String sql = "\\%\\_"; + String converted = SearchLanguageConversion.convert(SearchLanguageConversion.DEF_LUCENE, SearchLanguageConversion.DEF_SQL_LIKE, lucene); + assertEquals(sql, converted); + } + + public void testTokenizeString() + { + String[] res = SearchLanguageConversion.tokenizeString(""); + assertTrue(res.length == 1); + res = SearchLanguageConversion.tokenizeString("bob"); + assertTrue(res.length == 1); + assertEquals("bob", res[0]); + res = SearchLanguageConversion.tokenizeString(" bob "); + assertTrue(res.length == 1); + assertEquals("bob", res[0]); + res = SearchLanguageConversion.tokenizeString(" bob hope "); + assertTrue(res.length == 2); + assertEquals("bob", res[0]); + assertEquals("hope", res[1]); + res = SearchLanguageConversion.tokenizeString(" bob hope "); + assertTrue(res.length == 2); + assertEquals("bob", res[0]); + assertEquals("hope", res[1]); + res = SearchLanguageConversion.tokenizeString(" bob no hope "); + assertTrue(res.length == 3); + assertEquals("bob", res[0]); + assertEquals("no", res[1]); + assertEquals("hope", res[2]); + } +} diff --git a/data-model/src/test/resources/org/alfresco/repo/dictionary/commonpropertynschild_model.xml b/data-model/src/test/resources/org/alfresco/repo/dictionary/commonpropertynschild_model.xml new file mode 100644 index 0000000000..485e0aa6bf --- /dev/null +++ b/data-model/src/test/resources/org/alfresco/repo/dictionary/commonpropertynschild_model.xml @@ -0,0 +1,31 @@ + + + 'child' data model which defines specific aspects whose properties use that common namespace + Alfresco + 2013-10-21 + 1.0 + + + + + + + + + + + + + TestAspect + Specific aspect whose properties use that common namespace + + + + + d:int + + + + + + diff --git a/data-model/src/test/resources/org/alfresco/repo/dictionary/commonpropertynsparent_model.xml b/data-model/src/test/resources/org/alfresco/repo/dictionary/commonpropertynsparent_model.xml new file mode 100644 index 0000000000..773882a930 --- /dev/null +++ b/data-model/src/test/resources/org/alfresco/repo/dictionary/commonpropertynsparent_model.xml @@ -0,0 +1,12 @@ + + + 'parent' data model which defines a common property namespace + Alfresco + 2013-10-21 + 1.0 + + + + + + diff --git a/data-model/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model.properties b/data-model/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model.properties new file mode 100644 index 0000000000..319799ac26 --- /dev/null +++ b/data-model/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model.properties @@ -0,0 +1,22 @@ +test_dictionarydaotest.description=Model Description + +test_dictionarydaotest.class.test_base.title=Base Title +test_dictionarydaotest.class.test_base.description=Base Description + +test_dictionarydaotest.property.test_prop1.title=Prop1 Title +test_dictionarydaotest.property.test_prop1.description=Prop1 Description + +test_dictionarydaotest.association.test_assoc1.title=Assoc1 Title +test_dictionarydaotest.association.test_assoc1.description=Assoc1 Description + +test_dictionarydaotest.datatype.test_datatype.analyzer=Datatype Analyser + +listconstraint.test_list1.ABC=ABC display +listconstraint.test_list1.DEF=DEF display +listconstraint.test_list1.VALUE\ WITH\ SPACES=VALUE WITH SPACES display +listconstraint.test_list1.VALUE\ WITH\ TRAILING\ SPACE\ =VALUE WITH TRAILING SPACE display + +listconstraint.test_inlineConstraint.ALPHA=ALPHA display +listconstraint.test_inlineConstraint.BETA=BETA display +listconstraint.test_inlineConstraint.GAMMA,\ DELTA=GAMMA, DELTA display +# Intentionally no localisation for OMEGA. diff --git a/data-model/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model.xml b/data-model/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model.xml new file mode 100644 index 0000000000..5f317f446d --- /dev/null +++ b/data-model/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model.xml @@ -0,0 +1,366 @@ + + + Alfresco Content Model + Alfresco + 2005-05-30 + 1.0 + + + + + + + + + + + + + + org.alfresco.repo.search.impl.lucene.analysis.AlfrescoStandardAnalyser + alfresco/model/dataTypeAnalyzers + java.lang.Object + + + + + + + cm:reg1 + + + cm:reg2 + + + Regex1 title + Regex1 description + [A-Z]* + false + + + [a-z]* + false + + + 0 + 256 + + + 0 + 128 + + + 0 + 256 + + + List1 title + List1 description + + + ABC + DEF + VALUE WITH SPACES + VALUE WITH TRAILING SPACE + + + true + + + + + HIJ + + + true + + + + + XYZ + + + true + + + + + + + Base + The Base Type + + + + + d:text + true + + + + + Prop1 Strlen1 title + Prop1 Strlen1 description + + + + + + + + + + true + false + + + test:base + false + true + + + + + true + true + + + test:referenceable + false + false + + + + + true + true + + + test:referenceable + false + false + + fred + true + + + + true + true + + + test:referenceable + false + false + + fred + true + true + + + + + test:referenceable + + + + + test:base + true + + + + d:text + true + + + + + + + + + test:referenceable + + fred + true + + + + + + an overriden default value + + + + + + + + + + + test:file + + + + test:file + false + + + + test:base + + + d:text + true + + + + + + + test:base + + + d:text + true + + + d:text + true + + + d:text + true + + + + + + + + d:text + one + + + + + + test:overridetype1 + + + two + + + + + + test:overridetype2 + + + three + + + + + + Type with named property-defined constraint. + A type with a named constraint defined within one of its properties. + + + + + d:text + true + + + + Inline constraint + An inline constraint + + + ALPHA + BETA + GAMMA, DELTA + OMEGA + + + true + + + + + + + + + + Referenceable + The referenceable aspect + + + + + d:int + true + true + + true + false + + + + + + + + + Aspect Base + + + + d:text + + + + + + + + Aspect One + test:aspect-base + + + + + + + + + + Aspect Two + test:aspect-base + + + + + + + + + + + Aspect derived from other namespace + test:aspect-base + + + + + + + + + + + diff --git a/data-model/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model1.properties b/data-model/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model1.properties new file mode 100644 index 0000000000..7ff0b4b99c --- /dev/null +++ b/data-model/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model1.properties @@ -0,0 +1,21 @@ +test_dictionarydaotest.description=Model Description + +test_dictionarydaotest.class.test_base.title=Base Title +test_dictionarydaotest.class.test_base.description=Base Description + +test_dictionarydaotest.property.test_prop1.title=Prop1 Title +test_dictionarydaotest.property.test_prop1.description=Prop1 Description + +test_dictionarydaotest.association.test_assoc1.title=Assoc1 Title +test_dictionarydaotest.association.test_assoc1.description=Assoc1 Description + +test_dictionarydaotest.datatype.test_datatype.analyzer=Datatype Analyser + +listconstraint.test_list1.ABC=ABC display +listconstraint.test_list1.DEF=DEF display +listconstraint.test_list1.VALUE\ WITH\ SPACES=VALUE WITH SPACES display + +listconstraint.test_inlineConstraint.ALPHA=ALPHA display +listconstraint.test_inlineConstraint.BETA=BETA display +listconstraint.test_inlineConstraint.GAMMA,\ DELTA=GAMMA, DELTA display +# Intentionally no localisation for OMEGA. diff --git a/data-model/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model1.xml b/data-model/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model1.xml new file mode 100644 index 0000000000..10c6a08450 --- /dev/null +++ b/data-model/src/test/resources/org/alfresco/repo/dictionary/dictionarydaotest_model1.xml @@ -0,0 +1,84 @@ + + + Alfresco Content Model + Alfresco + 2005-05-30 + 1.0 + + + + + + + + + + + + + Base + Type 1 + cm:content + + + + d:text + true + + + + + + + + true + false + + + cm:content + false + true + + + + + true + true + + + cm:content + false + false + + fred + true + + + + + daotest1:aspect1 + + + + + + + Aspect1 + Aspect1 + + + + + d:int + true + true + + true + false + + + + + + + diff --git a/data-model/src/test/resources/org/alfresco/repo/dictionary/modelCircularTypes.xml b/data-model/src/test/resources/org/alfresco/repo/dictionary/modelCircularTypes.xml new file mode 100644 index 0000000000..41fe6f698b --- /dev/null +++ b/data-model/src/test/resources/org/alfresco/repo/dictionary/modelCircularTypes.xml @@ -0,0 +1,19 @@ + + + + + + + + + my:mytypeC + + + my:mytypeA + + + my:mytypeA + + + + \ No newline at end of file diff --git a/data-model/src/test/resources/org/alfresco/repo/dictionary/nstest_model.xml b/data-model/src/test/resources/org/alfresco/repo/dictionary/nstest_model.xml new file mode 100644 index 0000000000..b676d40846 --- /dev/null +++ b/data-model/src/test/resources/org/alfresco/repo/dictionary/nstest_model.xml @@ -0,0 +1,31 @@ + + + Test of namespace clashes + Alfresco + 2015-03-02 + 1.0 + + + + + + + + + + + + MyType + A Type + + + + + d:text + true + + + + + + diff --git a/data-model/src/test/resources/org/alfresco/repo/search/impl/parsers/cmis_fts_test.gunit b/data-model/src/test/resources/org/alfresco/repo/search/impl/parsers/cmis_fts_test.gunit new file mode 100644 index 0000000000..3d05ee6f05 --- /dev/null +++ b/data-model/src/test/resources/org/alfresco/repo/search/impl/parsers/cmis_fts_test.gunit @@ -0,0 +1,83 @@ +/** CMIS FTS */ + +gunit CMIS_FTS; + +@header{package org.alfresco.repo.search.impl.parsers;} + +/** Parser */ + +ftsCmisDisjunction: +"term1 term2 OR term3 term4" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM term1)) (DEFAULT (TERM term2))) (CONJUNCTION (DEFAULT (TERM term3)) (DEFAULT (TERM term4))))" +"'phrase one' 'phrase two' OR 'phrase three'" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (PHRASE 'phrase one')) (DEFAULT (PHRASE 'phrase two'))) (CONJUNCTION (DEFAULT (PHRASE 'phrase three'))))" +"-term OR -'phrase one' term2 OR -term3 'phrase two' OR 'phrase three'" -> "(DISJUNCTION (CONJUNCTION (EXCLUDE (TERM term))) (CONJUNCTION (EXCLUDE (PHRASE 'phrase one')) (DEFAULT (TERM term2))) (CONJUNCTION (EXCLUDE (TERM term3)) (DEFAULT (PHRASE 'phrase two'))) (CONJUNCTION (DEFAULT (PHRASE 'phrase three'))))" +"-term-one" -> "(DISJUNCTION (CONJUNCTION (EXCLUDE (TERM term-one))))" +"'it\\'s'" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (PHRASE 'it\\'s'))))" +// Invalid phrases end up as terms +"'it\'s'" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 'it's'))))" +"test" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM test))))" +"!test" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM !test))))" +"te!st" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM te!st))))" +"test!" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM test!))))" +"?test" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM ?test))))" +"te?st" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM te?st))))" +"test?" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM test?))))" +"*test" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM *test))))" +"te*st" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM te*st))))" +"test*" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM test*))))" + + +ftsCmisConjunction: +"term1 term2" -> "(CONJUNCTION (DEFAULT (TERM term1)) (DEFAULT (TERM term2)))" +"'phrase one' 'phrase two'" -> "(CONJUNCTION (DEFAULT (PHRASE 'phrase one')) (DEFAULT (PHRASE 'phrase two')))" +"-term -'phrase one' term2 -term3 'phrase two'" -> "(CONJUNCTION (EXCLUDE (TERM term)) (EXCLUDE (PHRASE 'phrase one')) (DEFAULT (TERM term2)) (EXCLUDE (TERM term3)) (DEFAULT (PHRASE 'phrase two')))" + +ftsCmisPrefixed: +"term" -> "(DEFAULT (TERM term))" +"'phrase one'" -> "(DEFAULT (PHRASE 'phrase one'))" +"-term" -> "(EXCLUDE (TERM term))" +"-'phrase one'" -> "(EXCLUDE (PHRASE 'phrase one'))" + + +cmisTest: +"term" -> "(TERM term)" +"'phrase one'" -> "(PHRASE 'phrase one')" + +cmisTerm: +"term" -> "term" + +cmisPhrase: +"'phrase one'" -> "'phrase one'" + +or: +"OR" -> "OR" + +/** Lexer */ + +FTSPHRASE: +"''" OK +"'meep'" OK +"'it\\'s'" OK +"'it\\'" FAIL +"'it\\\\'" OK +"'OR'" OK + +OR: +"OR" OK +"or" OK +"Or" OK +"oR" OK + +MINUS: +"-" OK + +WS: +" " OK +"\t" OK +"\r" OK +"\n" OK + +FTSWORD: +"word" OK +"wo-rd" OK + + diff --git a/data-model/src/test/resources/org/alfresco/repo/search/impl/parsers/cmis_test.gunit b/data-model/src/test/resources/org/alfresco/repo/search/impl/parsers/cmis_test.gunit new file mode 100644 index 0000000000..8482636d31 --- /dev/null +++ b/data-model/src/test/resources/org/alfresco/repo/search/impl/parsers/cmis_test.gunit @@ -0,0 +1,569 @@ +/** CMIS */ + +gunit CMIS; + +@header{package org.alfresco.repo.search.impl.parsers;} + +/** Parser */ + +query: +"SELECT * FROM cmis:document" OK +"SELECT * FROM cmis:document, cmis:folder" FAIL +"SELECT SCORE() FROM cmis:document" OK +"SELECT from FROM cmis:document" FAIL +"SELECT DOCUMENT.Name FROM cmis:document" OK +"SELECT cmis:name, cmis:typeId FROM cmis:document" OK +"SELECT document.* FROM cmis:document" OK +"SELECT cmis:name,, cmis:typeId FROM cmis:document" FAIL +"SELECT * FROM *" FAIL + +"SELECT * from cmis:document d JOIN cm:titled t ON d.cmis:objectId = t.cmis:objectId" -> + "(QUERY ALL_COLUMNS (SOURCE (TABLE_REF cmis:document d) (JOIN (SOURCE (TABLE_REF cm:titled t)) (ON (COLUMN_REF cmis:objectId d) = (COLUMN_REF cmis:objectId t)))))" +"SELECT * from cmis:document d LEFT OUTER JOIN cm:titled t ON d.cmis:objectId = t.cmis:objectId" -> + "(QUERY ALL_COLUMNS (SOURCE (TABLE_REF cmis:document d) (JOIN (SOURCE (TABLE_REF cm:titled t)) LEFT (ON (COLUMN_REF cmis:objectId d) = (COLUMN_REF cmis:objectId t)))))" +"SELECT * from cmis:document d JOIN cm:titled t ON d.cmis:objectId = t.cmis:objectId LEFT OUTER JOIN cm:ownable o ON d.cmis:objectId = o.cmis:objectId" -> + "(QUERY ALL_COLUMNS (SOURCE (TABLE_REF cmis:document d) (JOIN (SOURCE (TABLE_REF cm:titled t)) (ON (COLUMN_REF cmis:objectId d) = (COLUMN_REF cmis:objectId t))) (JOIN (SOURCE (TABLE_REF cm:ownable o)) LEFT (ON (COLUMN_REF cmis:objectId d) = (COLUMN_REF cmis:objectId o)))))" +"SELECT d.*, t.*, o.* from cmis:document d JOIN cm:titled t ON d.cmis:objectId = t.cmis:objectId LEFT OUTER JOIN cm:ownable o ON d.cmis:objectId = o.cmis:objectId" -> + "(QUERY (COLUMNS (ALL_COLUMNS d) (ALL_COLUMNS t) (ALL_COLUMNS o)) (SOURCE (TABLE_REF cmis:document d) (JOIN (SOURCE (TABLE_REF cm:titled t)) (ON (COLUMN_REF cmis:objectId d) = (COLUMN_REF cmis:objectId t))) (JOIN (SOURCE (TABLE_REF cm:ownable o)) LEFT (ON (COLUMN_REF cmis:objectId d) = (COLUMN_REF cmis:objectId o)))))" +"SELECT * from cmis:document d LEFT OUTER JOIN cm:titled t ON d.cmis:objectId = t.cmis:objectId" OK +"SELECT * from cmis:document d LEFT JOIN cm:titled t ON d.cmis:objectId = t.cmis:objectId" OK +"SELECT * from cmis:document d RIGHT OUTER JOIN cm:titled t ON d.cmis:objectId = t.cmis:objectId" FAIL +"SELECT * from cmis:document d RIGHT JOIN cm:titled t ON d.cmis:objectId = t.cmis:objectId" FAIL + +"SELECT * from FOLDER JOIN RELATIONSHIP ON FOLDER.ID = RELATIONSHIP.ID" OK +"SELECT * from FOLDER F JOIN RELATIONSHIP RL ON F.ID = RL.ID" OK +"SELECT * from DOCUMENT D JOIN DOCUMENT DD ON (D.ID = DD.ID)" FAIL +"SELECT * from FOLDER F JOIN RELATIONSHIP RL ON F.ID = RL.ID" OK +"SELECT * from (FOLDER F JOIN RELATIONSHIP RL ON F.ID = RL.ID)" OK +"SELECT * from ((FOLDER F JOIN RELATIONSHIP RL ON F.ID = RL.ID))" OK +"SELECT * from (FOLDER)" FAIL +"SELECT * from cmis:folder F INNER JOIN cmis:relationship RL ON F.ID = RL.ID" OK +"SELECT * from cmis:folder F LEFT JOIN cmis:relationship RL ON F.ID = RL.ID" OK +"SELECT * from FOLDER F LEFT OUTER JOIN RELATIONSHIP RL ON F.ID = RL.ID" OK +"SELECT * from FOLDER F LEFT INNER JOIN RELATIONSHIP RL ON F.ID = RL.ID" FAIL + +"SELECT * FROM cmis:document WHERE cmis:name='Test'" OK +"SELECT * FROM FOLDER WHERE COUNTER=7" OK +"SELECT * FROM FOLDER WHERE 7=COUNTER" FAIL +"SELECT * FROM FOLDER WHERE COUNTER IS NULL" OK +"SELECT * FROM FOLDER WHERE COUNTER IS NOT NULL" OK +"SELECT * FROM FOLDER WHERE COUNTER IS 5" FAIL +"SELECT * FROM FOLDER WHERE NAME LIKE '%te_t'" OK +"SELECT * FROM FOLDER WHERE COUNTER LIKE 5" FAIL +"SELECT * FROM FOLDER WHERE ANY NAME IN ('test', 'mail', 2)" OK +"SELECT * FROM FOLDER WHERE CONTAINS ('test -mail')" OK +"SELECT * FROM FOLDER WHERE IN_FOLDER('folderId')" OK +"SELECT * FROM FOLDER WHERE IN_TREE('folderId')" OK +"SELECT cmis:objectId FROM test:document where cmis:name='Test' AND counter>=22" OK +"SELECT cmis:objectId FROM test:document where (cmis:name='Test' AND counter<>22) OR CONTAINS('test')" OK +"SELECT cmis:objectId FROM test:document where ((cmis:name='Test' AND counter<=22) OR (CONTAINS('test') AND cmis:createdBy NOT LIKE 'J%')) AND (bill IS NULL)" OK + +"SELECT * FROM cmis:document WHERE cmis:name='Test' ORDER BY cmis:name" OK +"SELECT * FROM cmis:document WHERE cmis:name='Test' ORDER BY cmis:name ASC, cmis:type DESC" OK +"SELECT * FROM cmis:document WHERE cmis:name='Test' ORDER BY first lines" FAIL + +"SELECT Y.*, X.PROPERTY_ADDRESS FROM POLICY AS X JOIN CLAIMS AS Y ON X.POLICY_NUM = Y.POLICY_NUM WHERE ( ( Y.DAMAGE_ESTIMATES = 10000 OR cmis:createdBy NOT LIKE 'J%') AND (X.MAIN IS NULL) ) ORDER BY cmis:name ASC, cmis:type DESC" OK +"SELECT Name, Make FROM POLICY WHERE (MAKE = 'buick' ) OR ( ANY FEATURES IN ('NAVIGATION SYSTEM', 'SATELLITE RADIO', 'MP3') ) OR IN_FOLDER('folderId')" OK +"SELECT DOC.NAME, DOC.TYPE, P.Info, SCORE() FROM cmis:document AS DOC LEFT OUTER JOIN POLICY P ON P.DOC_ID = DOC.ID WHERE (DOC.NAME LIKE 'Test%' AND P.INFO <> 'dual' AND DOC.NUM >=44) OR CONTAINS('test') OR DOC.NAME IS NOT NULL ORDER BY cmis:name ASC" OK +"SELECT Name, SCORE() FROM POLICY JOIN DOCUMENT WHERE (MAKE = 'buick' ) OR (FEATURES IS ('NAVIGATION SYSTEM', 'MP3') )" FAIL + + +selectList: +"*" OK +//"column1" OK +//"column1, column2" OK +"column1, *" FAIL +"column1,, column2" FAIL +"X.column1, Y.column2" OK +"X.*" OK +"X.1, X.Y.Z" FAIL + +"*" -> "ALL_COLUMNS" +"X.*" -> "(COLUMNS (ALL_COLUMNS X))" +//"column1, column2" -> "(COLUMNS (COLUMN (COLUMN_REF column1)) (COLUMN (COLUMN_REF column2)))" +"X.column1, Y.column2" -> "(COLUMNS (COLUMN (COLUMN_REF column1 X)) (COLUMN (COLUMN_REF column2 Y)))" +"SCORE()" -> (COLUMNS (COLUMN (FUNCTION SCORE ( )))) + +//selectSubList: +//"column1" OK + +//valueExpression: +//"column1" OK + +columnReference: +"column1" OK + +fromClause: +"FROM table1" OK +"FROM table1 T" OK +"FROM table1 AS T" OK +"FROM table1 JOIN table2 ON column1 = column2" OK +"FROM table1 JOIN table2" FAIL +"FROM table1 T1 JOIN table2 T2 ON T1.column1 = T2.column2" OK +"FROM table1 T1 LEFT JOIN table2 T2 ON T1.column1 = T2.column2" OK +"FROM table1 T1 LEFT INNER JOIN table2 T2 ON T1.column1 = T2.column2" FAIL +"FROM table1 T1 LEFT OUTER JOIN table2 T2 ON T1.column1 = T2.column2" OK +"FROM table1 T1 INNER JOIN table2 T2 ON T1.column1 = T2.column2" OK +"FROM table1 T1 LEFT OUTER JOIN table2 T2 ON T1.column1 = T2.column2 INNER JOIN table3 ON T2.column2 = table3.column2" OK +"FROM table1 T1 JOIN table2 T2 ON T1.column1 = T2.column1 JOIN table3 ON T2.column2 = table3.column2" OK +"FROM ((table1 T1 JOIN table2 T2 ON T1.column1 = T2.column1) LEFT JOIN table3 T3 ON T2.column1 = T3.column1)" OK + +"FROM table1" -> "(SOURCE (TABLE_REF table1))" +"FROM table1 AS T" -> "(SOURCE (TABLE_REF table1 T))" +"FROM table1 JOIN table2 ON column1 = column2" -> "(SOURCE (TABLE_REF table1) (JOIN (SOURCE (TABLE_REF table2)) (ON (COLUMN_REF column1) = (COLUMN_REF column2))))" +"FROM table1 LEFT OUTER JOIN table2 ON column1 = column2" -> "(SOURCE (TABLE_REF table1) (JOIN (SOURCE (TABLE_REF table2)) LEFT (ON (COLUMN_REF column1) = (COLUMN_REF column2))))" + +whereClause: +"WHERE column1 = 'value1'" OK +"WHERE 3.32 = ANY column1" OK +"WHERE column1 = value1" FAIL +"WHERE T.column1 = 'value1'" OK +"WHERE T.T.column1 = 'value1'" FAIL +"WHERE column1 = true" OK +"WHERE column1 = 3.32" OK +"WHERE column1 > 3.32" OK +"WHERE column1 >= 3.32" OK +"WHERE column1 => 3.32" FAIL +"WHERE column1 < 3.32" OK +"WHERE column1 <= 3.32" OK +"WHERE column1 =< 3.32" FAIL +"WHERE column1 <> 3.32" OK +"WHERE column1 >< 3.32" FAIL +"WHERE 2.22 < column1 < 3.32" FAIL + +"WHERE CONTAINS('test string')" OK +"WHERE CONTAINS(22)" FAIL +"WHERE IN_FOLDER('folderId')" OK +"WHERE IN_TREE('folderId')" OK +"WHERE column1 IS NULL" OK +"WHERE column1 IS NOT NULL" OK +"WHERE column1 NOT IS NULL" FAIL +"WHERE column1 LIKE 'T%'" OK +"WHERE column1 NOT LIKE 'T%'" OK +"WHERE column1 LIKE 2%" FAIL +"WHERE column1 IN (1, 2, 3)" OK +"WHERE ANY column1 IN (1, 2, 3)" OK +"WHERE column1 NOT IN (1, 2, 3)" OK +"WHERE column1 IN ('A', 'B')" OK +"WHERE column1 IN (A, B)" FAIL +"WHERE column1 IN (True)" OK + +"WHERE col1=1 AND col2=2" OK +"WHERE col1=1 OR col2=2" OK +"WHERE (col1=1 AND col2=2)" OK +"WHERE NOT (col1=1 AND col2=2)" OK +"WHERE ((col1=1 OR col2=2))" OK +"WHERE ((col1=1 OR col2=2)" FAIL +"WHERE (col1=1 AND col2=2) OR col2=3" OK +"WHERE col1=1 AND ((col2=2) OR col2=3)" OK +"WHERE (col1=1 AND (col2=2 OR col2=3)" FAIL +"WHERE NOT(col2=2) OR NOT(col2=3)" OK +"WHERE NOT(col2=2 OR col2=3)" OK +"WHERE NOT(col2=2 AND NOT(col3=3)) OR NOT(col1=1)" OK +"WHERE col4=4 AND NOT(col2=2 AND NOT(col3=3)) OR NOT(col1=1)" OK +"WHERE col4=4 AND (col2=2 NOT(col3=3)) OR NOT(col1=1)" FAIL + +"WHERE (NOT(col2 < 2.25) OR NOT CONTAINS('text')) AND col3 LIKE 'T__T'" OK +"WHERE 2 = ANY col1 OR col2 IN (2.25, 3.25) OR ((col2 IS NOT NULL OR col3 LIKE 'T%') AND IN_TREE('folder_id'))" OK +"WHERE ((NOT (col2 IS NOT NULL) OR col3 LIKE 'T%') AND CONTAINS ('TEXT')) OR (col1 >='A' AND col2 IN (2.25, 3.25))" OK + +"WHERE column1 = 'value1'" -> "(DISJUNCTION (CONJUNCTION (PRED_COMPARISON SINGLE_VALUED_PROPERTY (COLUMN_REF column1) = (STRING_LITERAL 'value1'))))" +"WHERE 'value1'= ANY column1" -> "(DISJUNCTION (CONJUNCTION (PRED_COMPARISON ANY (STRING_LITERAL 'value1') = (COLUMN_REF column1))))" +"WHERE column1 > 3.32" -> "(DISJUNCTION (CONJUNCTION (PRED_COMPARISON SINGLE_VALUED_PROPERTY (COLUMN_REF column1) > (NUMERIC_LITERAL 3.32))))" +"WHERE CONTAINS('test string')" -> "(DISJUNCTION (CONJUNCTION (PRED_FTS 'test string')))" +"WHERE IN_FOLDER('folderId')" -> "(DISJUNCTION (CONJUNCTION (PRED_CHILD (STRING_LITERAL 'folderId'))))" +"WHERE IN_TREE('folderId')" -> "(DISJUNCTION (CONJUNCTION (PRED_DESCENDANT (STRING_LITERAL 'folderId'))))" +"WHERE column1 IS NULL" -> "(DISJUNCTION (CONJUNCTION (PRED_EXISTS (COLUMN_REF column1) NOT)))" +"WHERE column1 LIKE 'T%'" -> "(DISJUNCTION (CONJUNCTION (PRED_LIKE (COLUMN_REF column1) (STRING_LITERAL 'T%'))))" +"WHERE column1 IN (1, 2)" -> "(DISJUNCTION (CONJUNCTION (PRED_IN SINGLE_VALUED_PROPERTY (COLUMN_REF column1) (LIST (NUMERIC_LITERAL 1) (NUMERIC_LITERAL 2)))))" +"WHERE NOT(col1=1)" -> "(DISJUNCTION (CONJUNCTION (NEGATION (DISJUNCTION (CONJUNCTION (PRED_COMPARISON SINGLE_VALUED_PROPERTY (COLUMN_REF col1) = (NUMERIC_LITERAL 1)))))))" +"WHERE col1=1 AND col2=2" -> "(DISJUNCTION (CONJUNCTION (PRED_COMPARISON SINGLE_VALUED_PROPERTY (COLUMN_REF col1) = (NUMERIC_LITERAL 1)) (PRED_COMPARISON SINGLE_VALUED_PROPERTY (COLUMN_REF col2) = (NUMERIC_LITERAL 2))))" +"WHERE col1=1 OR col2=2" -> "(DISJUNCTION (CONJUNCTION (PRED_COMPARISON SINGLE_VALUED_PROPERTY (COLUMN_REF col1) = (NUMERIC_LITERAL 1))) (CONJUNCTION (PRED_COMPARISON SINGLE_VALUED_PROPERTY (COLUMN_REF col2) = (NUMERIC_LITERAL 2))))" + +orderByClause: +"ORDER BY column1" OK +"ORDER BY ASC" FAIL +"ORDER BY column1 ASC" OK +"ORDER BY column1 DESC" OK +"ORDER BY column1 value" FAIL +"ORDER BY column1, column2" OK +"ORDER BY column1, column2 ASC" OK +"ORDER BY column1 ASC, column2 DESC" OK + +"ORDER BY column1" -> "(ORDER (SORT_SPECIFICATION (COLUMN_REF column1) ASC))" +"ORDER BY column1 ASC, column2 DESC" -> "(ORDER (SORT_SPECIFICATION (COLUMN_REF column1) ASC) (SORT_SPECIFICATION (COLUMN_REF column2) DESC))" + +datetimeLiteral: +"TIMESTAMP '2009-12-09T13:22:15.250'" OK +"TIMESTAMP '2009-12-09T13:22:15.250Z'" OK +"TIMESTAMP '2009-12-09T13:22:15.250+02:30'" OK +"TIMESTAMP '2009-12-09T13:22:15.250-02:30'" OK +/* Should fail as " are not valid quotes in CMIS or SQL */ +"TIMESTAMP \"2009-12-09T13:22:15.250-02:30\"" FAIL +/* Not checked at parse time */ +"TIMESTAMP '2009-12-9T13:22:15.250+2:30'" OK +/* The date format is checked during query processing and not parsing */ +"TIMESTAMP 'Thu Dec 10 16:19:53 EET 2009'" OK + +textSearchExpression: +"'word1'" OK +"'word1 -word2'" OK +"'word1 -word2 word3'" OK +"'word1 -word2 OR word3'" OK +/** OR is not treated as a special keyword */ +"'word1-word2 OR OR word3'" OK +/** Spec spcifies minimum */ +"'word1-word2 \"word1 OR word3\"'" OK +"'word1 \"phrase_word1 phrase_word2\"'" OK +/** "'word1 'phrase_word1 phrase_word2''" FAIL this failsas invalid */ + + +/** Lexer */ + +QUOTED_STRING: +"'test string'" OK +"test string" FAIL +"'string\\''" OK +"''test string'" FAIL +"'cmis:name:\\'Folder 9\\\\\\'\\''" OK + +SELECT: +"SELECT" OK +"sElECt" OK +"SeLECT" OK +"seLEct" OK +"SELect" OK +"SElECt" OK +"seLect" OK +"sElEcT" OK +"select" OK + +AS: +"AS" OK +"aS" OK +"As" OK +"as" OK + +FROM: +"FROM" OK +"fRom" OK +"FROM" OK +"FroM" OK +"fROM" OK +"FRoM" OK +"from" OK + +JOIN: +"JOIN" OK +"JOiN" OK +"join" OK +"JoIN" OK +"jOiN" OK +"Join" OK +"join" OK + +INNER: +"INNER" OK +"innEr" OK +"iNNer" OK +"INnER" OK +"iNnEr" OK +"InNer" OK +"InneR" OK +"inner" OK + +LEFT: +"LEFT" OK +"leFt" OK +"lEfT" OK +"LEft" OK +"lefT" OK +"Left" OK +"left" OK + +OUTER: +"OUTER" OK +"oUtEr" OK +"OUTEr" OK +"outER" OK +"OUtEr" OK +"OutEr" OK +"oUTer" OK +"outer" OK + +ON: +"ON" OK +"oN" OK +"On" OK +"on" OK + +WHERE: +"WHERE" OK +"wheRe" OK +"WHere" OK +"WhERE" OK +"WHERe" OK +"WHErE" OK +"whEre" OK +"where" OK + +OR: +"OR" OK +"oR" OK +"Or" OK +"or" OK + +AND: +"AND" OK +"ANd" OK +"AnD" OK +"aNd" OK +"And" OK +"and" OK + +NOT: +"NOT" OK +"NoT" OK +"nOT" OK +"Not" OK +"noT" OK +"not" OK + +IN: +"IN" OK +"iN" OK +"In" OK +"in" OK + +LIKE: +"LIKE" OK +"LIkE" OK +"lIke" OK +"lIKe" OK +"liKE" OK +"lIkE" OK +"like" OK + +IS: +"IS" OK +"iS" OK +"Is" OK +"is" OK + +NULL: +"NULL" OK +"nulL" OK +"NUll" OK +"NuLl" OK +"nULL" OK +"NULL" OK +"null" OK + +ANY: +"ANY" OK +"aNy" OK +"AnY" OK +"aNY" OK +"Any" OK +"any" OK + +CONTAINS: +"CONTAINS" OK +"ContAINS" OK +"coNtainS" OK +"coNTainS" OK +"cONTAiNS" OK +"ContAIns" OK +"ConTains" OK +"CONTaiNS" OK +"CONtaiNs" OK +"COnTAiNS" OK +"contains" OK + +IN_FOLDER: +"IN_FOLDER" OK +"In_FoldeR" OK +"In_FoldEr" OK +"IN_fOlDeR" OK +"in_FOLdeR" OK +"iN_fOLder" OK +"IN_FOlder" OK +"iN_FOLdER" OK +"in_fOLdEr" OK +"iN_FOLDer" OK +"in_FOLdER" OK +"in_folder" OK + +IN_TREE: +"IN_TREE" OK +"IN_TRee" OK +"In_tREE" OK +"IN_tRee" OK +"in_trEe" OK +"In_TReE" OK +"IN_TRee" OK +"In_tRee" OK +"iN_treE" OK +"in_tree" OK + +ORDER: +"ORDER" OK +"Order" OK +"ORDeR" OK +"OrdeR" OK +"orDER" OK +"oRdEr" OK +"ORder" OK +"order" OK + +BY: +"BY" OK +"bY" OK +"By" OK +"by" OK + +ASC: +"ASC" OK +"asC" OK +"Asc" OK +"ASc" OK +"aSC" OK +"asc" OK + +DESC: +"DESC" OK +"deSC" OK +"DEsC" OK +"dESc" OK +"DeSC" OK +"dESC" OK +"desc" OK + +TIMESTAMP: +"TIMESTAMP" OK +"tiMEsTaMP" OK +"TImESTaMp" OK +"tImesTAMP" OK +"TImEstaMp" OK +"timesTAMp" OK +"TIMEsTaMP" OK +"tiMESTAMP" OK +"timeSTamp" OK +"tIMESTamp" OK +"tImEsTAmp" OK +"timestamp" OK + +TRUE: +"TRUE" OK +"tRUE" OK +"True" OK +"TRUE" OK +"truE" OK +"tRUe" OK +"true" OK + +FALSE: +"FALSE" OK +"fALsE" OK +"FAlSE" OK +"fAlSe" OK +"FalSe" OK +"fALSE" OK +"fALsE" OK +"false" OK + +SCORE: +"SCORE" OK +"SCore" OK +"score" OK +"ScOrE" OK +"scOrE" OK +"sCore" OK +"SCoRe" OK +"score" OK + +LPAREN: +"(" OK + +RPAREN: +")" OK + +STAR: +"*" OK + +COMMA: +"," OK + +DOTSTAR: +".*" OK + +DOT: +"." OK + +DOTDOT: +".." OK + +EQUALS: +"=" OK + +TILDA: +"~" OK + +NOTEQUALS: +"<>" OK + +GREATERTHAN: +">" OK + +LESSTHAN: +"<" OK + +GREATERTHANOREQUALS: +">=" OK + +LESSTHANOREQUALS: +"<=" OK + +COLON: +":" OK + +DOUBLE_QUOTE: +"\"" OK + +ID: +"test_id" OK +"" FAIL +"a" OK +"_" OK +"$" FAIL +"_$" OK +"#" FAIL +"_#" OK +"1" FAIL +"A1" OK +"abcABC_abcABC0123_:$#" OK + +DECIMAL_INTEGER_LITERAL: +"0" OK +"-1" OK +"1" OK +"01" FAIL +"10" OK +"-10" OK +"+150" OK + +FLOATING_POINT_LITERAL: +"0" FAIL +"1.." FAIL +"1." OK +"-1.0" OK +"1..0" FAIL +"1...." FAIL +"1.0.." FAIL +"-1.02" OK +"1e10" OK +"1.2e-12" OK +"0.9E-9" OK +"+123.123456" OK + + \ No newline at end of file diff --git a/data-model/src/test/resources/org/alfresco/repo/search/impl/parsers/fts_test.gunit b/data-model/src/test/resources/org/alfresco/repo/search/impl/parsers/fts_test.gunit new file mode 100644 index 0000000000..feca453d73 --- /dev/null +++ b/data-model/src/test/resources/org/alfresco/repo/search/impl/parsers/fts_test.gunit @@ -0,0 +1,509 @@ +/** FTS */ + +gunit FTS; + +@header{package org.alfresco.repo.search.impl.parsers;} + +/** Parser */ + +ftsQuery: +"\"zebra\"" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (PHRASE \"zebra\"))))" +"one and cm:name:two and cm_name:three and {http://www.alfresco.org/model/content/1.0}name:\"four\" seven * eight \"nine * ten\"" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM one)) (DEFAULT (TERM two (FIELD_REF name (PREFIX cm)))) (DEFAULT (TERM three (FIELD_REF cm_name))) (DEFAULT (PHRASE \"four\" (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))) (DEFAULT (PROXIMITY seven PROXIMITY eight)) (DEFAULT (PHRASE \"nine * ten\"))))" +"1..2" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (RANGE INCLUSIVE 1 2 INCLUSIVE))))" +"test:flag:true AND %test:field" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM true (FIELD_REF flag (PREFIX test)))) (DEFAULT (TEMPLATE (FIELD_REF field (PREFIX test))))))" +"test:flag:true AND %NEST" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM true (FIELD_REF flag (PREFIX test)))) (DEFAULT (TEMPLATE (FIELD_REF NEST)))))" +"test:flag:true AND %(NEST, test:field, test_field1, {http://www.alfresco.org/model/content/1.0}name)" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM true (FIELD_REF flag (PREFIX test)))) (DEFAULT (TEMPLATE (FIELD_REF NEST) (FIELD_REF field (PREFIX test)) (FIELD_REF test_field1) (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0}))))))" +"+PATH:\"/app:company_home/st:sites/cm:rmtestnew1/cm:documentLibrary//*\" +(ASPECT:\"{http://www.alfresco.org/model/recordsmanagement/1.0}record\") -TYPE:\"{http://www.alfresco.org/model/content/1.0}thumbnail\"" -> "(DISJUNCTION (CONJUNCTION (MANDATORY (PHRASE \"/app:company_home/st:sites/cm:rmtestnew1/cm:documentLibrary//*\" (FIELD_REF PATH))) (MANDATORY (DISJUNCTION (CONJUNCTION (DEFAULT (PHRASE \"{http://www.alfresco.org/model/recordsmanagement/1.0}record\" (FIELD_REF ASPECT)))))) (EXCLUDE (PHRASE \"{http://www.alfresco.org/model/content/1.0}thumbnail\" (FIELD_REF TYPE)))))" +"TEXT:(\"lazy\")" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (FIELD_GROUP (FIELD_REF TEXT) (FIELD_DISJUNCTION (FIELD_CONJUNCTION (FIELD_DEFAULT (FG_PHRASE \"lazy\"))))))))" +"test.txt" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM test . txt))))" +"=test.txt" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (EXACT_TERM test . txt))))" +"test.txt.woof" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM test . txt . woof))))" +"test_txt_woof" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM test_txt_woof))))" +"test,txt,woof" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM test , txt , woof))))" +"test\:txt\:woof" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM test\\:txt\\:woof))))" +"+\++" -> "(DISJUNCTION (CONJUNCTION (MANDATORY (TERM \\++))))" +".txt" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM . txt))))" +"*.txt" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM * . txt))))" +".txt.doc.banana" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM . txt . doc . banana))))" +"quick * fox" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (PROXIMITY quick PROXIMITY fox))))" +"*.txt" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM * . txt))))" +"doc.*" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM doc . *))))" +"{http://www.alfresco.org/test/lucenetest}float\\-ista:3..3.40" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (RANGE INCLUSIVE 3 3.40 INCLUSIVE (FIELD_REF float\\-ista (NAME_SPACE {http://www.alfresco.org/test/lucenetest}))))))" +".10." -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM . 10 .))))" +".1.2.3.4" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM . 1 . 2 . 3 . 4))))" +".1.2.3.4." -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM . 1 . 2 . 3 . 4.))))" +"1.2.3.4" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 1 . 2 . 3.4))))" +"1.2.3.4." -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 1 . 2 . 3 . 4 .))))" +".ab." -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM . ab .))))" +"a.b.c" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM a . b . c))))" +"0" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 0))))" +"1.." FAIL +"1." -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 1.))))" +"1.2..1.3"-> "(DISJUNCTION (CONJUNCTION (DEFAULT (RANGE INCLUSIVE 1.2 1.3 INCLUSIVE))))" +"1.0" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 1.0))))" +"1..0" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (RANGE INCLUSIVE 1 0 INCLUSIVE))))" +"1..." FAIL +"1...2." FAIL +"1...2" FAIL +"1...." FAIL +"1.0.." FAIL +"-1.02" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM -1.02))))" +"1e10" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 1e10))))" +"1.2e-12" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 1.2e-12))))" +"0.9E-9" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 0.9E-9))))" +".." FAIL +"." FAIL +"0" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 0))))" +"-1" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM -1))))" +"1" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 1))))" +"01" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 01))))" +"10" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 10))))" +"-10" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM -10))))" +"cm_content.mimetype:\"text/plain\"" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (PHRASE \"text/plain\" (FIELD_REF cm_content.mimetype)))))" +"10.10.pdf" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 10 . 10 . pdf))))" +"TYPE:cm:content" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM content (FIELD_REF cm (PREFIX TYPE))))))" +"TYPE:content" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM content (FIELD_REF TYPE)))))" +"TYPE:\"cm:content\"" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (PHRASE \"cm:content\" (FIELD_REF TYPE)))))" +"TYPE:\"content\"" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (PHRASE \"content\" (FIELD_REF TYPE)))))" +"created:[* TO *]" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (RANGE INCLUSIVE * * INCLUSIVE (FIELD_REF created)))))" +"TYPE:{http://www.alfresco.org/model/content/1.0}folder" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM {http://www.alfresco.org/model/content/1.0} folder (FIELD_REF TYPE)))))" +"wlss\:FourBC\:'BEBO'" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM wlss\\:FourBC\\:'BEBO'))))" +"wlss\:4BC\:'BEBO'" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM wlss\\:4BC\\:'BEBO'))))" +"1a" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 1a))))" +"1b:1a" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 1a (FIELD_REF 1b)))))" +"1c:1b:1a" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM 1a (FIELD_REF 1b (PREFIX 1c))))))" +"1:a:needle" FAIL +"a:1:needle" FAIL + + +ftsDisjunction: +"red" -> (DISJUNCTION (CONJUNCTION (DEFAULT (TERM red)))) +"red or blue" -> (DISJUNCTION (CONJUNCTION (DEFAULT (TERM red))) (CONJUNCTION (DEFAULT (TERM blue)))) +"red or blue OR pink" -> (DISJUNCTION (CONJUNCTION (DEFAULT (TERM red))) (CONJUNCTION (DEFAULT (TERM blue))) (CONJUNCTION (DEFAULT (TERM pink)))) + + +ftsExplicitDisjunction: +"red" -> (DISJUNCTION (CONJUNCTION (DEFAULT (TERM red)))) +"red or blue" -> (DISJUNCTION (CONJUNCTION (DEFAULT (TERM red))) (CONJUNCTION (DEFAULT (TERM blue)))) +"red or blue OR pink" -> (DISJUNCTION (CONJUNCTION (DEFAULT (TERM red))) (CONJUNCTION (DEFAULT (TERM blue))) (CONJUNCTION (DEFAULT (TERM pink)))) + + +ftsExplicitConjunction: +"red" -> (CONJUNCTION (DEFAULT (TERM red))) +"red and blue" -> (CONJUNCTION (DEFAULT (TERM red)) (DEFAULT (TERM blue))) +"red and blue AND pink" -> (CONJUNCTION (DEFAULT (TERM red)) (DEFAULT (TERM blue)) (DEFAULT (TERM pink))) + +ftsPrefixed: +"not zebra" -> (NEGATION (TERM zebra)) +"zebra" -> (DEFAULT (TERM zebra)) +"+zebra" -> (MANDATORY (TERM zebra)) +"|zebra" -> (OPTIONAL (TERM zebra)) +"-zebra" -> (EXCLUDE (TERM zebra)) + + +ftsTest: +"zebra" -> (TERM zebra) +"\"zebra\"" -> (PHRASE "zebra") +"or" FAIL +"\\+" -> (TERM \+) +"+" FAIL +"name:woof" -> "(TERM woof (FIELD_REF name))" +"cm_name:woof" -> "(TERM woof (FIELD_REF cm_name))" +"cm:name:woof" -> "(TERM woof (FIELD_REF name (PREFIX cm)))" +"{http://www.alfresco.org/model/content/1.0}name:woof" -> "(TERM woof (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))" +"name:\"woof\"" -> "(PHRASE \"woof\" (FIELD_REF name))" +"cm_name:\"woof\"" -> "(PHRASE \"woof\" (FIELD_REF cm_name))" +"cm:name:\"woof\"" -> "(PHRASE \"woof\" (FIELD_REF name (PREFIX cm)))" +"{http://www.alfresco.org/model/content/1.0}name:\"woof\"" -> "(PHRASE \"woof\" (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))" +"=name:woof" -> "(EXACT_TERM woof (FIELD_REF name))" +"=cm_name:woof" -> "(EXACT_TERM woof (FIELD_REF cm_name))" +"=cm:name:woof" -> "(EXACT_TERM woof (FIELD_REF name (PREFIX cm)))" +"={http://www.alfresco.org/model/content/1.0}name:woof" -> "(EXACT_TERM woof (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))" +"~name:woof" -> "(TERM woof (FIELD_REF name))" +"~cm_name:woof" -> "(TERM woof (FIELD_REF cm_name))" +"~cm:name:woof" -> "(TERM woof (FIELD_REF name (PREFIX cm)))" +"~{http://www.alfresco.org/model/content/1.0}name:woof" -> "(TERM woof (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))" +"apple..pear" -> "(RANGE INCLUSIVE apple pear INCLUSIVE)" +"1..2" -> "(RANGE INCLUSIVE 1 2 INCLUSIVE)" +"1\.2..2\.5" -> "(RANGE INCLUSIVE 1\\.2 2\\.5 INCLUSIVE)" +"\"apple\"..\"pear\"" -> "(RANGE INCLUSIVE \"apple\" \"pear\" INCLUSIVE)" +"\"1.2\"..\"2.5\"" -> "(RANGE INCLUSIVE \"1.2\" \"2.5\" INCLUSIVE)" +"name:apple..pear" -> "(RANGE INCLUSIVE apple pear INCLUSIVE (FIELD_REF name))" +"name:1..2" -> "(RANGE INCLUSIVE 1 2 INCLUSIVE (FIELD_REF name))" +"name:1\.2..2\.5" -> "(RANGE INCLUSIVE 1\\.2 2\\.5 INCLUSIVE (FIELD_REF name))" +"name:\"apple\"..\"pear\"" -> "(RANGE INCLUSIVE \"apple\" \"pear\" INCLUSIVE (FIELD_REF name))" +"name:\"1.2\"..\"2.5\"" -> "(RANGE INCLUSIVE \"1.2\" \"2.5\" INCLUSIVE (FIELD_REF name))" +"cm_name:apple..pear" -> "(RANGE INCLUSIVE apple pear INCLUSIVE (FIELD_REF cm_name))" +"cm_name:1..2" -> "(RANGE INCLUSIVE 1 2 INCLUSIVE (FIELD_REF cm_name))" +"cm_name:1\.2..2\.5" -> "(RANGE INCLUSIVE 1\\.2 2\\.5 INCLUSIVE (FIELD_REF cm_name))" +"cm_name:\"apple\"..\"pear\"" -> "(RANGE INCLUSIVE \"apple\" \"pear\" INCLUSIVE (FIELD_REF cm_name))" +"cm_name:\"1.2\"..\"2.5\"" -> "(RANGE INCLUSIVE \"1.2\" \"2.5\" INCLUSIVE (FIELD_REF cm_name))" +"cm:name:apple..pear" -> "(RANGE INCLUSIVE apple pear INCLUSIVE (FIELD_REF name (PREFIX cm)))" +"cm:name:1..2" -> "(RANGE INCLUSIVE 1 2 INCLUSIVE (FIELD_REF name (PREFIX cm)))" +"cm:name:1\.2..2\.5" -> "(RANGE INCLUSIVE 1\\.2 2\\.5 INCLUSIVE (FIELD_REF name (PREFIX cm)))" +"cm:name:\"apple\"..\"pear\"" -> "(RANGE INCLUSIVE \"apple\" \"pear\" INCLUSIVE (FIELD_REF name (PREFIX cm)))" +"cm:name:\"1.2\"..\"2.5\"" -> "(RANGE INCLUSIVE \"1.2\" \"2.5\" INCLUSIVE (FIELD_REF name (PREFIX cm)))" +"{http://www.alfresco.org/model/content/1.0}name:apple..pear" -> "(RANGE INCLUSIVE apple pear INCLUSIVE (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))" +"{http://www.alfresco.org/model/content/1.0}name:1..2" -> "(RANGE INCLUSIVE 1 2 INCLUSIVE (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))" +"{http://www.alfresco.org/model/content/1.0}name:1\.2..2\.5" -> "(RANGE INCLUSIVE 1\\.2 2\\.5 INCLUSIVE (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))" +"{http://www.alfresco.org/model/content/1.0}name:\"apple\"..\"pear\"" -> "(RANGE INCLUSIVE \"apple\" \"pear\" INCLUSIVE (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))" +"{http://www.alfresco.org/model/content/1.0}name:\"1.2\"..\"2.5\"" -> "(RANGE INCLUSIVE \"1.2\" \"2.5\" INCLUSIVE (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))" +"cm:name:(woof)" -> "(FIELD_GROUP (FIELD_REF name (PREFIX cm)) (FIELD_DISJUNCTION (FIELD_CONJUNCTION (FIELD_DEFAULT (FG_TERM woof)))))" +"cm:name:(\"woof\")" -> "(FIELD_GROUP (FIELD_REF name (PREFIX cm)) (FIELD_DISJUNCTION (FIELD_CONJUNCTION (FIELD_DEFAULT (FG_PHRASE \"woof\")))))" +"cm:name:(woof ~banana)" -> "(FIELD_GROUP (FIELD_REF name (PREFIX cm)) (FIELD_DISJUNCTION (FIELD_CONJUNCTION (FIELD_DEFAULT (FG_TERM woof)) (FIELD_DEFAULT (FG_SYNONYM banana)))))" +"big * apple" -> "(PROXIMITY big PROXIMITY apple)" +"big *() apple" -> "(PROXIMITY big PROXIMITY apple)" +"big *(7) apple" -> "(PROXIMITY big (PROXIMITY 7) apple)" +"1.5" -> "(TERM 1.5)" +"cm:name:1.5" -> "(TERM 1.5 (FIELD_REF name (PREFIX cm)))" +"cm:name:12" -> "(TERM 12 (FIELD_REF name (PREFIX cm)))" +"zebr*" -> "(TERM zebr*)" +"zebra~2" -> "(TERM zebra (FUZZY 2))" +"cm:name:zebra~2.4" -> "(TERM zebra (FIELD_REF name (PREFIX cm)) (FUZZY 2.4))" +"\"zebra\"~2" -> "(PHRASE \"zebra\" (FUZZY 2))" +"{http://www.alfresco.org/model/content/1.0}name:\"zebra\"~3" -> "(PHRASE \"zebra\" (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})) (FUZZY 3))" +"=zebra~2" -> "(EXACT_TERM zebra (FUZZY 2))" +"=cm_name:zebra~2.4" -> "(EXACT_TERM zebra (FIELD_REF cm_name) (FUZZY 2.4))" +"~zebra~2" -> "(TERM zebra (FUZZY 2))" +"~cm_name:zebra~2.4" -> "(TERM zebra (FIELD_REF cm_name) (FUZZY 2.4))" +"aardvark..zebra" -> "(RANGE INCLUSIVE aardvark zebra INCLUSIVE)" +"cm_name:[1.2 TO 3.4]" -> "(RANGE INCLUSIVE 1.2 3.4 INCLUSIVE (FIELD_REF cm_name))" +"(zebra~2 AND (cm_name:[1.2 TO 3.4] OR cm_name:zebra~2.4))" -> "(DISJUNCTION (CONJUNCTION (DEFAULT (TERM zebra (FUZZY 2))) (DEFAULT (DISJUNCTION (CONJUNCTION (DEFAULT (RANGE INCLUSIVE 1.2 3.4 INCLUSIVE (FIELD_REF cm_name)))) (CONJUNCTION (DEFAULT (TERM zebra (FIELD_REF cm_name) (FUZZY 2.4))))))))" +"ID * OR" FAIL +"*" -> "(TERM *)" +"name:*" -> "(TERM * (FIELD_REF name))" +"cm:name:*" -> "(TERM * (FIELD_REF name (PREFIX cm)))" +"?" -> "(TERM ?)" +"name:?" -> "(TERM ? (FIELD_REF name))" +"cm:name:?" -> "(TERM ? (FIELD_REF name (PREFIX cm)))" +"*woof" -> "(TERM *woof)" +"name:*woof" -> "(TERM *woof (FIELD_REF name))" +"cm:name:*woof" -> "(TERM *woof (FIELD_REF name (PREFIX cm)))" +"?woof" -> "(TERM ?woof)" +"name:?woof" -> "(TERM ?woof (FIELD_REF name))" +"cm:name:?woof" -> "(TERM ?woof (FIELD_REF name (PREFIX cm)))" +"woof*woof" ->"(TERM woof*woof)" +"woof * woof" ->"(PROXIMITY woof PROXIMITY woof)" +"*woof*woof*" ->"(TERM *woof*woof*)" +"cm:content.mimetype:*" -> "(TERM * (FIELD_REF content.mimetype (PREFIX cm)))" + + +ftsTermOrPhrase: +"name:woof" -> "(TERM woof (FIELD_REF name))" +"cm_name:woof" -> "(TERM woof (FIELD_REF cm_name))" +"cm:name:woof" -> "(TERM woof (FIELD_REF name (PREFIX cm)))" +"{http://www.alfresco.org/model/content/1.0}name:woof" -> "(TERM woof (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))" +"\"zebra\"" -> "(PHRASE \"zebra\")" +"'zebra'" -> "(PHRASE 'zebra')" +"name:\"zebra\"" -> "(PHRASE \"zebra\" (FIELD_REF name))" +"cm_name:\"zebra\"" -> "(PHRASE \"zebra\" (FIELD_REF cm_name))" +"cm:name:\"zebra\"" -> "(PHRASE \"zebra\" (FIELD_REF name (PREFIX cm)))" +"{http://www.alfresco.org/model/content/1.0}name:\"zebra\"" -> "(PHRASE \"zebra\" (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))" + + + +ftsExactTermOrPhrase: +"=name:woof" -> "(EXACT_TERM woof (FIELD_REF name))" +"=cm_name:woof" -> "(EXACT_TERM woof (FIELD_REF cm_name))" +"=cm:name:woof" -> "(EXACT_TERM woof (FIELD_REF name (PREFIX cm)))" +"={http://www.alfresco.org/model/content/1.0}name:woof" -> "(EXACT_TERM woof (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))" + + + +ftsTokenisedTermOrPhrase: +"~woof" -> "(TERM woof)" +"~name:woof" -> "(TERM woof (FIELD_REF name))" +"~cm_name:woof" -> "(TERM woof (FIELD_REF cm_name))" +"~cm:name:woof" -> "(TERM woof (FIELD_REF name (PREFIX cm)))" +"~{http://www.alfresco.org/model/content/1.0}name:woof" -> "(TERM woof (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))" + + +// groups ... + +// Term and phrase can not be tested in isolation as they have context +ftsFieldGroupTest: +//"woof" -> "(FG_TERM woof)" +//"=woof" -> "(FG_EXACT_TERM woof)" +//"\"woof\"" -> "(FG_PHRASE \"woof\")" +//"~woof" -> "(FG_SYNONYM woof)" +"apple * pear" -> "(FG_PROXIMITY apple PROXIMITY pear)" +"12 .. 14" -> "(FG_RANGE INCLUSIVE 12 14 INCLUSIVE)" +"[12 TO 14]" -> "(FG_RANGE INCLUSIVE 12 14 INCLUSIVE)" +"<12 TO 14>" -> "(FG_RANGE EXCLUSIVE 12 14 EXCLUSIVE)" +"(apple cheese and (pear or banana or not orange))" -> "(FIELD_DISJUNCTION (FIELD_CONJUNCTION (FIELD_DEFAULT (FG_TERM apple)) (FIELD_DEFAULT (FG_TERM cheese)) (FIELD_DEFAULT (FIELD_DISJUNCTION (FIELD_CONJUNCTION (FIELD_DEFAULT (FG_TERM pear))) (FIELD_CONJUNCTION (FIELD_DEFAULT (FG_TERM banana))) (FIELD_CONJUNCTION (FIELD_NEGATION (FG_TERM orange)))))))" +"(apple chesse and banana)" -> (FIELD_DISJUNCTION (FIELD_CONJUNCTION (FIELD_DEFAULT (FG_TERM apple)) (FIELD_DEFAULT (FG_TERM chesse)) (FIELD_DEFAULT (FG_TERM banana)))) +"(apple chesse and not banana)" -> (FIELD_DISJUNCTION (FIELD_CONJUNCTION (FIELD_DEFAULT (FG_TERM apple)) (FIELD_DEFAULT (FG_TERM chesse)) (FIELD_NEGATION (FG_TERM banana)))) +"(apple chesse and (not banana))" -> (FIELD_DISJUNCTION (FIELD_CONJUNCTION (FIELD_DEFAULT (FG_TERM apple)) (FIELD_DEFAULT (FG_TERM chesse)) (FIELD_DEFAULT (FIELD_DISJUNCTION (FIELD_CONJUNCTION (FIELD_NEGATION (FG_TERM banana))))))) +ftsFieldGroupTerm: +"woof" -> "woof" + +ftsFieldGroupExactTerm: +"=woof" -> "woof" + +ftsFieldGroupPhrase: +"\"zebra\"" -> "\"zebra\"" + +ftsFieldGroupSynonym: +"~woof" -> "woof" + +// ?? +ftsFieldGroupProximity: +"big * panda" -> "big PROXIMITY panda" + +ftsFieldGroupRange: +"apple..pear" -> "INCLUSIVE apple pear INCLUSIVE" +"1..2" -> "INCLUSIVE 1 2 INCLUSIVE" +"1\.2..2\.5" -> "INCLUSIVE 1\.2 2\.5 INCLUSIVE" +"\"apple\"..\"pear\"" -> "INCLUSIVE \"apple\" \"pear\" INCLUSIVE" +"\"1.2\"..\"2.5\"" -> "INCLUSIVE \"1.2\" \"2.5\" INCLUSIVE" +"[apple TO pear]" -> "INCLUSIVE apple pear INCLUSIVE" +"[apple TO pear>" -> "INCLUSIVE apple pear EXCLUSIVE" +" "EXCLUSIVE apple pear INCLUSIVE" +"" -> "EXCLUSIVE apple pear EXCLUSIVE" +"1....2" FAIL +"1.0..0.2" -> "INCLUSIVE 1.0 0.2 INCLUSIVE" +"1.2..2.5" -> "INCLUSIVE 1.2 2.5 INCLUSIVE" +"[1.2 TO 2.5]" -> "INCLUSIVE 1.2 2.5 INCLUSIVE" + +range_left: +"[" -> "INCLUSIVE" +"<" -> "EXCLUSIVE" + +range_right: +"]" -> "INCLUSIVE" +">" -> "EXCLUSIVE" + +fieldReference: +//"name" OK +//"cm_name" OK +// Fails do to context sensitive colon check; tested above +//"cm:name" OK +"{http://www.alfresco.org/model/content/1.0}name" OK + + +uri: +"{http://www.alfresco.org/model/dictionary/1.0}" OK + +identifier: +"banana" OK +"name" OK +"content.mimetype" OK + +ftsWord: +"OR" FAIL +"and" FAIL +"nOT" -> "nOT" +"TO" -> "TO" +"banana" -> "banana" +"1234" -> "1234" + +ftsRangeWord: +"banana" -> "banana" +"1234" -> "1234" +"\"phrase\"" -> "\"phrase\"" +"1\.5" ->"1\.5" + +or: +"OR" OK +"or" OK +"||" OK +"|" FAIL + +and: +"AND" OK +"and" OK +"&&" OK +"&" FAIL + + +not: +"NOT" OK +"not" OK +"!" OK + +/** Lexer */ + +FTSPHRASE: +"nope" FAIL +"\"\"" OK +"\"\\\"" FAIL +"\"\"\"" FAIL +"\"\\u\"" OK +"\"\phrase\"" OK + +URI: +"{http://www.ics.uci.edu/pub/ietf/uri/#Related}" OK +"{http://www.alfresco.org}" OK +"{http://www.alfresco.org/model/dictionary/1.0}" OK +"{http://www.alfresco.org/view/repository/1.0}" OK + + +OR: +"OR" OK +"Or" OK +"oR" OK +"or" OK + +AND: +"AND" OK +"ANd" OK +"AnD" OK +"And" OK +"aND" OK +"aNd" OK +"anD" OK +"and" OK + +NOT: +"NOT" OK +"NOt" OK +"NoT" OK +"Not" OK +"nOT" OK +"nOt" OK +"noT" OK +"not" OK + + +TILDA: +"~" OK + +LPAREN: +"(" OK + +RPAREN: +")" OK + +PLUS: +"+" OK + +MINUS: +"-" OK + +COLON: +":" OK + +STAR: +"*" OK + +AMP: +"&" OK + +EXCLAMATION: +"!" OK + +BAR: +"|" OK + +EQUALS: +"=" OK + +QUESTION_MARK: +"?" OK + +LCURL: +"{" OK + +RCURL: +"}" OK + +LSQUARE: +"[" OK + +RSQUARE: +"]" OK + +TO: +"TO" OK +"To" OK +"tO" OK +"to" OK + + +COMMA: +"," OK + +CARAT: +"^" OK + +DOLLAR: +"$" OK + +ID : +"banana" OK +"" FAIL +"a" OK +"_" OK +"$" FAIL +"_$" OK +"#" FAIL +"_#" OK +"1" FAIL +"A1" OK +"1A" OK +"0_" OK +"0123456789$#" FAIL +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" OK +"cm:name" FAIL + + +FTSWORD: +"word" OK +"\\u0" FAIL +"\\u00" FAIL +"\\u000" FAIL +"\\u0000" OK +"\\u1234" OK +"\\u5678" OK +"\\u90AB" OK +"\\uCDEF" OK +"\\u90ab" OK +"\\ucdef" OK +"\\u3005" OK +"\\u000h" FAIL +"\\u000H" FAIL +"\\u" OK +"\\~" OK +"\\(" OK +"\\)" OK +"\\+" OK +"\\-" OK +"\\:" OK +"\\*" OK +"\\." OK +"\\&" OK +"\\!" OK +"\\|" OK +"\\=" OK +"\\?" OK +"\\{" OK +"\\}" OK +"\\[" OK +"\\]" OK +"\\," OK +"\\^" OK +"\\$" OK +"\\\\" OK +"@" FAIL // 40 invalid +"A" OK +"Z" OK +"[" FAIL +"`" FAIL +"a" OK +"z" OK +"{" FAIL +//"×" FAIL +//"Ø" OK +//"÷" FAIL +//"ə" OK +"(" FAIL +")" FAIL +" " FAIL +"\u3000" OK +"\\u3000" OK +"  " FAIL +//"㐀" OK + + + +